Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing issue with automated ride hail getting simulations stuck #3766

Draft
wants to merge 9 commits into
base: develop
Choose a base branch
from
Draft
15 changes: 15 additions & 0 deletions src/main/scala/beam/sim/BeamHelper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,18 @@ trait BeamHelper extends LazyLogging with BeamValidationHelper {
outputDir: String,
plansMerged: Boolean
): Unit = {
BeamHelper.synchronized {
if (
BeamHelper.lastSimulationStartTime > 0 &&
System.currentTimeMillis() - BeamHelper.lastSimulationStartTime < BeamHelper.simulationStartupWaitMs
) {
val wait =
BeamHelper.simulationStartupWaitMs - (System.currentTimeMillis() - BeamHelper.lastSimulationStartTime)
logger.error(s"Waiting for $wait ms before starting a new Beam simulation.")
Thread.sleep(wait)
}
BeamHelper.lastSimulationStartTime = System.currentTimeMillis()
}
if (!beamScenario.beamConfig.beam.agentsim.fractionOfPlansWithSingleActivity.equals(0d)) {
applyFractionOfPlansWithSingleActivity(scenario, beamServices.beamConfig, scenario.getConfig)
}
Expand Down Expand Up @@ -1074,6 +1086,9 @@ trait BeamHelper extends LazyLogging with BeamValidationHelper {

object BeamHelper {

var lastSimulationStartTime: Long = -1L
val simulationStartupWaitMs: Int = 5000

/**
* We need to copy the old config values to the first element of rideHail.managers collection.
* It helps workaround the typesafe config limitation that one cannot access array elements via paths
Expand Down
6 changes: 6 additions & 0 deletions src/main/scala/beam/utils/StuckFinder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,19 @@ class StuckFinder(val cfg: StuckAgentDetection) extends LazyLogging {
result
}

private var maxTimeoutObserved = 0L

def isStuckAgent(st: ScheduledTrigger, startedAtMs: Long, currentTimeMs: Long): Boolean = {
val diff = currentTimeMs - startedAtMs
val threshold = class2Threshold.getOrElse(toKey(st), cfg.defaultTimeoutMs)
val isStuck = diff > threshold
if (isStuck) {
logger.warn(s"$st is stuck. Diff: $diff ms, Threshold: $threshold ms")
}
if (maxTimeoutObserved < diff) {
maxTimeoutObserved = diff
logger.error(s"$st just set a new maximum observed timeout of $maxTimeoutObserved milliseconds")
}
isStuck
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import beam.utils.EventReader
import beam.utils.TestConfigUtils.testConfig
import com.typesafe.config.ConfigFactory
import org.matsim.api.core.v01.Id
import org.scalatest.BeforeAndAfterAll
import org.matsim.api.core.v01.events.Event
import org.matsim.vehicles.Vehicle
import org.scalatest.AppendedClues.convertToClueful
Expand All @@ -20,6 +21,7 @@ import scala.util.matching.Regex
class ElectricVehicleChargingBehaviorTest
extends AnyFlatSpec
with Matchers
with BeforeAndAfterAll
with BeamHelper
with BeforeAndAfterAllConfigMap {

Expand Down Expand Up @@ -416,8 +418,9 @@ class ElectricVehicleChargingBehaviorTest
", expecting most of the 4 legs for each of the 50 people to be ride hail legs."
}

// test ignored due to an issue with AV RH which for some reason is much more likely to trigger on this test
"Ride Hail Electric vehicles" should "pick chargers choosing smaller DrivingTimeCost." ignore {
// this test gets stuck on CI, investigation lead to the conclusion that the culprit is AV RH
// getting stuck when beam simulations are running in parallel
"Ride Hail Electric vehicles" should "pick chargers choosing smaller DrivingTimeCost." in {
// this config is only interested on the first charging plugin event when,
// vehicles are at known coordinates, population plans are set to walk to not interfere with ride hail.
val config = ConfigFactory
Expand Down Expand Up @@ -578,6 +581,18 @@ class ElectricVehicleChargingBehaviorTest
", vehicles should be picking the faster chargers (more power output) more often than the slower ones."
}

override val invokeBeforeAllAndAfterAllEvenIfNoTestsAreExpected = true

override def beforeAll(): Unit = {
logger.error("ElectricVehicleChargingBehaviorTest started.")
super.beforeAll()
}

override def afterAll(): Unit = {
logger.error("ElectricVehicleChargingBehaviorTest ended.")
super.afterAll()
}

def filterEvents(events: IndexedSeq[Event], filters: (String, String => Boolean)*): IndexedSeq[Event] = {
events.filter(event =>
filters.forall(filter =>
Expand Down
77 changes: 77 additions & 0 deletions test/input/beamville/beam-av-rh-10k.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
include "beam.conf"

beam.physsim.name = "AV RH beamville 10k"
beam.agentsim.endTime = "24:00:00"

# base config
matsim.modules.global.randomSeed = 654154
beam.outputs.events.fileOutputFormats = xml
beam.physsim.skipPhysSim = true
beam.agentsim.lastIteration = 0
beam.agentsim.agents.vehicles.sharedFleets = []
beam.agentsim.taz.filePath=${beam.inputDirectory}"/../../test-resources/ElectricVehicleChargingBehaviorTestData/taz-centers.csv"

# rideHailConfig
beam.agentsim.agents.rideHail.managers = [
{
iterationStats.timeBinSizeInSec = 3600
defaultCostPerMile = 1.25
defaultCostPerMinute = 0.75
rideHailManager.radiusInMeters = 50000
# allocationManager(DEFAULT_MANAGER | EV_MANAGER | POOLING_ALONSO_MORA)
allocationManager.name = "POOLING_ALONSO_MORA"
allocationManager.requestBufferTimeoutInSeconds = 200
allocationManager.maxWaitingTimeInSec = 18000
allocationManager.maxExcessRideTime = 0.5 # up to +50%
allocationManager.matchingAlgorithm = "ALONSO_MORA_MATCHING_WITH_ASYNC_GREEDY_ASSIGNMENT"
allocationManager.alonsoMora.maxRequestsPerVehicle = 5
repositioningManager.name = "DEMAND_FOLLOWING_REPOSITIONING_MANAGER"
repositioningManager.timeout = 300
# DEMAND_FOLLOWING_REPOSITIONING_MANAGER
repositioningManager.demandFollowingRepositioningManager.sensitivityOfRepositioningToDemand = 1
repositioningManager.demandFollowingRepositioningManager.numberOfClustersForDemand = 30
# REPOSITIONING_LOW_WAITING_TIMES
allocationManager.repositionLowWaitingTimes.percentageOfVehiclesToReposition = 0.0
allocationManager.repositionLowWaitingTimes.repositionCircleRadiusInMeters = 100
allocationManager.repositionLowWaitingTimes.timeWindowSizeInSecForDecidingAboutRepositioning = 12000
allocationManager.repositionLowWaitingTimes.allowIncreasingRadiusIfDemandInRadiusLow = true
allocationManager.repositionLowWaitingTimes.minDemandPercentageInRadius = 0.1
allocationManager.repositionLowWaitingTimes.minimumNumberOfIdlingVehiclesThresholdForRepositioning = 1000
allocationManager.repositionLowWaitingTimes.repositioningMethod = "TOP_SCORES"
allocationManager.repositionLowWaitingTimes.keepMaxTopNScores = 5
allocationManager.repositionLowWaitingTimes.minScoreThresholdForRepositioning = 100000000.0
allocationManager.repositionLowWaitingTimes.distanceWeight = 0.01
allocationManager.repositionLowWaitingTimes.waitingTimeWeight = 4.0
allocationManager.repositionLowWaitingTimes.demandWeight = 4.0
allocationManager.repositionLowWaitingTimes.produceDebugImages = true
initialization.filePath = ${beam.inputDirectory}"/../../test-resources/AVRH/10k/rideHailFleet.csv"
initialization.initType="FILE"
initialization.parking.filePath=${beam.inputDirectory}"/../../test-resources/ElectricVehicleChargingBehaviorTestData/taz-parking-empty.csv"
}
]
beam.agentsim.agents.plans {
inputPlansFilePath = ${beam.inputDirectory}"/../../test-resources/AVRH/10k/population.xml"
inputPersonAttributesFilePath = ${beam.inputDirectory}"/../../test-resources/AVRH/10k/populationAttributes.xml"
}
beam.agentsim.agents.households {
inputFilePath = ${beam.inputDirectory}"/../../test-resources/AVRH/10k/households.xml"
inputHouseholdAttributesFilePath = ${beam.inputDirectory}"/../../test-resources/AVRH/10k/householdAttributes.xml"
}
beam.agentsim.agents.vehicles.vehiclesFilePath = ${beam.inputDirectory}"/../../test-resources/ElectricVehicleChargingBehaviorTestData/vehicles-empty.csv"
beam.agentsim.agents.parking.minSearchRadius = 8000

# test config
beam.agentsim.agents.plans.inputPlansFilePath = ${beam.inputDirectory}"/../../test-resources/AVRH/10k/population.xml"
beam.agentsim.taz.parkingFilePath = ${beam.inputDirectory}"/../../test-resources/ElectricVehicleChargingBehaviorTestData/taz-parking-ride-hail-driving-time-cost.csv"
# 15 Km range
#beam.agentsim.agents.vehicles.vehicleTypesFilePath = ${beam.inputDirectory}"/../../test-resources/ElectricVehicleChargingBehaviorTestData/vehicleTypes-low-capacity.csv"
beam.agentsim.agents.vehicles.vehicleTypesFilePath = ${beam.inputDirectory}"/../../test-resources/AVRH/vehicleTypes-60km-range.csv"
#beam.agentsim.agents.vehicles.vehicleTypesFilePath = ${beam.inputDirectory}"/vehicleTypes_withL5.csv"
beam.agentsim.agents.rideHail.charging.multinomialLogit.params.drivingTimeMultiplier = -0.01666667 # default
# initial SoC is 0.7 or 10.5 Km, vehicles should immediately pick a charging station
beam.agentsim.agents.modalBehaviors.multinomialLogit.params.ride_hail_intercept = 0
#beam.agentsim.agents.rideHail.human.refuelRequiredThresholdInMeters = 11000.0
#beam.agentsim.agents.rideHail.human.noRefuelThresholdInMeters = 12000.0
#beam.agentsim.agents.rideHail.cav.refuelRequiredThresholdInMeters = 11000.0
#beam.agentsim.agents.rideHail.cav.noRefuelThresholdInMeters = 12000.0
#beam.agentsim.agents.rideHail.rangeBufferForDispatchInMeters = 0
77 changes: 77 additions & 0 deletions test/input/beamville/beam-av-rh-3k.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
include "beam.conf"

beam.physsim.name = "AV RH beamville 3k"
beam.agentsim.endTime = "24:00:00"

# base config
matsim.modules.global.randomSeed = 654154
beam.outputs.events.fileOutputFormats = xml
beam.physsim.skipPhysSim = true
beam.agentsim.lastIteration = 0
beam.agentsim.agents.vehicles.sharedFleets = []
beam.agentsim.taz.filePath=${beam.inputDirectory}"/../../test-resources/ElectricVehicleChargingBehaviorTestData/taz-centers.csv"

# rideHailConfig
beam.agentsim.agents.rideHail.managers = [
{
iterationStats.timeBinSizeInSec = 3600
defaultCostPerMile = 1.25
defaultCostPerMinute = 0.75
rideHailManager.radiusInMeters = 50000
# allocationManager(DEFAULT_MANAGER | EV_MANAGER | POOLING_ALONSO_MORA)
allocationManager.name = "POOLING_ALONSO_MORA"
allocationManager.requestBufferTimeoutInSeconds = 200
allocationManager.maxWaitingTimeInSec = 18000
allocationManager.maxExcessRideTime = 0.5 # up to +50%
allocationManager.matchingAlgorithm = "ALONSO_MORA_MATCHING_WITH_ASYNC_GREEDY_ASSIGNMENT"
allocationManager.alonsoMora.maxRequestsPerVehicle = 5
repositioningManager.name = "DEMAND_FOLLOWING_REPOSITIONING_MANAGER"
repositioningManager.timeout = 300
# DEMAND_FOLLOWING_REPOSITIONING_MANAGER
repositioningManager.demandFollowingRepositioningManager.sensitivityOfRepositioningToDemand = 1
repositioningManager.demandFollowingRepositioningManager.numberOfClustersForDemand = 30
# REPOSITIONING_LOW_WAITING_TIMES
allocationManager.repositionLowWaitingTimes.percentageOfVehiclesToReposition = 0.0
allocationManager.repositionLowWaitingTimes.repositionCircleRadiusInMeters = 100
allocationManager.repositionLowWaitingTimes.timeWindowSizeInSecForDecidingAboutRepositioning = 12000
allocationManager.repositionLowWaitingTimes.allowIncreasingRadiusIfDemandInRadiusLow = true
allocationManager.repositionLowWaitingTimes.minDemandPercentageInRadius = 0.1
allocationManager.repositionLowWaitingTimes.minimumNumberOfIdlingVehiclesThresholdForRepositioning = 1000
allocationManager.repositionLowWaitingTimes.repositioningMethod = "TOP_SCORES"
allocationManager.repositionLowWaitingTimes.keepMaxTopNScores = 5
allocationManager.repositionLowWaitingTimes.minScoreThresholdForRepositioning = 100000000.0
allocationManager.repositionLowWaitingTimes.distanceWeight = 0.01
allocationManager.repositionLowWaitingTimes.waitingTimeWeight = 4.0
allocationManager.repositionLowWaitingTimes.demandWeight = 4.0
allocationManager.repositionLowWaitingTimes.produceDebugImages = true
initialization.filePath = ${beam.inputDirectory}"/../../test-resources/AVRH/3k/rideHailFleet.csv"
initialization.initType="FILE"
initialization.parking.filePath=${beam.inputDirectory}"/../../test-resources/ElectricVehicleChargingBehaviorTestData/taz-parking-empty.csv"
}
]
beam.agentsim.agents.plans {
inputPlansFilePath = ${beam.inputDirectory}"/../../test-resources/AVRH/3k/population.xml"
inputPersonAttributesFilePath = ${beam.inputDirectory}"/../../test-resources/AVRH/3k/populationAttributes.xml"
}
beam.agentsim.agents.households {
inputFilePath = ${beam.inputDirectory}"/../../test-resources/AVRH/3k/households.xml"
inputHouseholdAttributesFilePath = ${beam.inputDirectory}"/../../test-resources/AVRH/3k/householdAttributes.xml"
}
beam.agentsim.agents.vehicles.vehiclesFilePath = ${beam.inputDirectory}"/../../test-resources/ElectricVehicleChargingBehaviorTestData/vehicles-empty.csv"
beam.agentsim.agents.parking.minSearchRadius = 8000

# test config
beam.agentsim.agents.plans.inputPlansFilePath = ${beam.inputDirectory}"/../../test-resources/AVRH/3k/population.xml"
beam.agentsim.taz.parkingFilePath = ${beam.inputDirectory}"/../../test-resources/ElectricVehicleChargingBehaviorTestData/taz-parking-ride-hail-driving-time-cost.csv"
# 15 Km range
#beam.agentsim.agents.vehicles.vehicleTypesFilePath = ${beam.inputDirectory}"/../../test-resources/ElectricVehicleChargingBehaviorTestData/vehicleTypes-low-capacity.csv"
beam.agentsim.agents.vehicles.vehicleTypesFilePath = ${beam.inputDirectory}"/../../test-resources/AVRH/vehicleTypes-60km-range.csv"
#beam.agentsim.agents.vehicles.vehicleTypesFilePath = ${beam.inputDirectory}"/vehicleTypes_withL5.csv"
beam.agentsim.agents.rideHail.charging.multinomialLogit.params.drivingTimeMultiplier = -0.01666667 # default
# initial SoC is 0.7 or 10.5 Km, vehicles should immediately pick a charging station
beam.agentsim.agents.modalBehaviors.multinomialLogit.params.ride_hail_intercept = 0
#beam.agentsim.agents.rideHail.human.refuelRequiredThresholdInMeters = 11000.0
#beam.agentsim.agents.rideHail.human.noRefuelThresholdInMeters = 12000.0
#beam.agentsim.agents.rideHail.cav.refuelRequiredThresholdInMeters = 11000.0
#beam.agentsim.agents.rideHail.cav.noRefuelThresholdInMeters = 12000.0
#beam.agentsim.agents.rideHail.rangeBufferForDispatchInMeters = 0
67 changes: 3 additions & 64 deletions test/input/beamville/beam.conf
Original file line number Diff line number Diff line change
Expand Up @@ -224,79 +224,18 @@ beam.debug.actor.logDepth = 12
beam.debug.stuckAgentDetection {
checkIntervalMs = 200
checkMaxNumberOfMessagesEnabled = true
defaultTimeoutMs = 60000
defaultTimeoutMs = 300000
enabled = true
overallSimulationTimeoutMs = 100000
overallSimulationTimeoutMs = 300000
thresholds = [
{
actorTypeToMaxNumberOfMessages {
population = 1
rideHailAgent = 1
transitDriverAgent = 1
}
markAsStuckAfterMs = 20000
markAsStuckAfterMs = 300000
triggerType = "beam.agentsim.agents.InitializeTrigger"
},
{
actorTypeToMaxNumberOfMessages {
population = 11
}
markAsStuckAfterMs = 20000
triggerType = "beam.agentsim.agents.PersonAgent$ActivityEndTrigger"
},
{
actorTypeToMaxNumberOfMessages {
population = 1
}
markAsStuckAfterMs = 20000
triggerType = "beam.agentsim.agents.PersonAgent$ActivityStartTrigger"
},
{
actorTypeToMaxNumberOfMessages {
population = 60
}
markAsStuckAfterMs = 20000
triggerType = "beam.agentsim.agents.PersonAgent$PersonDepartureTrigger"
},
{
actorTypeToMaxNumberOfMessages {
population = 20
}
markAsStuckAfterMs = 20000
triggerType = "beam.agentsim.agents.modalbehaviors.DrivesVehicle$AlightVehicleTrigger"
},
{
actorTypeToMaxNumberOfMessages {
population = 20
}
markAsStuckAfterMs = 20000
triggerType = "beam.agentsim.agents.modalbehaviors.DrivesVehicle$BoardVehicleTrigger"
},
{
actorTypeToMaxNumberOfMessages {
population = 80
rideHailAgent = 400
transitDriverAgent = 114
}
markAsStuckAfterMs = 20000
triggerType = "beam.agentsim.agents.modalbehaviors.DrivesVehicle$EndLegTrigger"
},
{
actorTypeToMaxNumberOfMessages {
population = 80
rideHailAgent = 400
transitDriverAgent = 114
}
markAsStuckAfterMs = 20000
triggerType = "beam.agentsim.agents.modalbehaviors.DrivesVehicle$StartLegTrigger"
},
{
actorTypeToMaxNumberOfMessages {
transitDriverAgent = 1
}
markAsStuckAfterMs = 20000
triggerType = "beam.agentsim.scheduler.BeamAgentScheduler$KillTrigger"

}
]
}
Expand Down
3 changes: 3 additions & 0 deletions test/test-resources/AVRH/10k/householdAttributes.xml
Git LFS file not shown
3 changes: 3 additions & 0 deletions test/test-resources/AVRH/10k/households.xml
Git LFS file not shown
3 changes: 3 additions & 0 deletions test/test-resources/AVRH/10k/population.xml
Git LFS file not shown
3 changes: 3 additions & 0 deletions test/test-resources/AVRH/10k/populationAttributes.xml
Git LFS file not shown
3 changes: 3 additions & 0 deletions test/test-resources/AVRH/10k/rideHailFleet.csv
Git LFS file not shown
3 changes: 3 additions & 0 deletions test/test-resources/AVRH/3k/householdAttributes.xml
Git LFS file not shown
3 changes: 3 additions & 0 deletions test/test-resources/AVRH/3k/households.xml
Git LFS file not shown
3 changes: 3 additions & 0 deletions test/test-resources/AVRH/3k/population.xml
Git LFS file not shown
3 changes: 3 additions & 0 deletions test/test-resources/AVRH/3k/populationAttributes.xml
Git LFS file not shown
3 changes: 3 additions & 0 deletions test/test-resources/AVRH/3k/rideHailFleet.csv
Git LFS file not shown
3 changes: 3 additions & 0 deletions test/test-resources/AVRH/vehicleTypes-60km-range.csv
Git LFS file not shown