From de64f772c6c69f612f977e605c558928f71f639c Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Thu, 27 Jun 2024 19:39:25 +0200 Subject: [PATCH 1/2] * repair wrong positioning of vehicles if linkSpeedCalculator returns speed larger than free speed * replace some (but not all) link.getAttributes()... by BicycleUtils.set/getXyz( link, ...) * bind BicycleConfigGroup explicitly in BicycleModule so that not materializing it before does not lead to a non-interpretable error message (stating that Scenario is not bound about 20 times although that is not the root of the problem) * possibly one or the other additional things --- ...BicycleLinkSpeedCalculatorDefaultImpl.java | 5 +- .../matsim/contrib/bicycle/BicycleModule.java | 30 ++++++--- .../BicycleTravelDisutilityFactory.java | 19 +++--- .../matsim/contrib/bicycle/BicycleUtils.java | 7 ++ .../network/BicycleOsmNetworkReaderV2.java | 2 +- .../controler/ControlerDefaultsModule.java | 3 +- .../AbstractAgentSnapshotInfoBuilder.java | 19 ++++-- .../qsim/qnetsimengine/QueueWithBuffer.java | 67 ++++++++++--------- .../EquiDistAgentSnapshotInfoBuilderTest.java | 10 +-- .../QueueAgentSnapshotInfoBuilderTest.java | 14 ++-- 10 files changed, 103 insertions(+), 73 deletions(-) diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java index f580b7e77f1..f6e5104fa86 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleLinkSpeedCalculatorDefaultImpl.java @@ -18,7 +18,10 @@ public final class BicycleLinkSpeedCalculatorDefaultImpl implements BicycleLinkS private static final Logger log = LogManager.getLogger(BicycleLinkSpeedCalculatorDefaultImpl.class ); @Inject private BicycleConfigGroup bicycleConfigGroup; @Inject private QSimConfigGroup qSimConfigGroup; - @Inject private BicycleLinkSpeedCalculatorDefaultImpl() { } + @Inject private Config config; + @Inject private BicycleLinkSpeedCalculatorDefaultImpl() { + } + /** * for unit testing */ diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java index 7bf5a766bf4..45e03c8a2f9 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java @@ -22,8 +22,12 @@ import com.google.inject.Singleton; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.checkerframework.checker.units.qual.C; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.config.ConfigUtils; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.events.StartupEvent; import org.matsim.core.controler.listener.StartupListener; @@ -34,30 +38,34 @@ * @author smetzler, dziemke */ public final class BicycleModule extends AbstractModule { - private static final Logger LOG = LogManager.getLogger(BicycleModule.class); - @Inject - private BicycleConfigGroup bicycleConfigGroup; + @Override public void install() { + BicycleConfigGroup bicycleConfigGroup = ConfigUtils.addOrGetModule( this.getConfig(), BicycleConfigGroup.class ); + this.bind( BicycleConfigGroup.class ).toInstance( bicycleConfigGroup ); + // the above feels odd. But it seems to work. I actually have no idea where the config groups are bound, neither for the core config + // groups nor for the added config groups. In general, the original idea was that AbstractModule provides the config from + // getConfig(), not from injection. kai, jun'24 - @Override - public void install() { // The idea here is the following: // * scores are just added as score events. no scoring function is replaced. // * link speeds are computed via a plugin handler to the DefaultLinkSpeedCalculator. If the plugin handler returns a speed, it is // used, otherwise the default speed is used. This has the advantage that multiple plugins can register such special link speed calculators. + // this gives the typical things to the router: addTravelTimeBinding(bicycleConfigGroup.getBicycleMode()).to(BicycleTravelTime.class).in(Singleton.class); addTravelDisutilityFactoryBinding(bicycleConfigGroup.getBicycleMode()).to(BicycleTravelDisutilityFactory.class).in(Singleton.class); + // (the BicycleTravelTime uses the BicycleLinkSpeed Calculator bound below) + // (the BicycleDisutility uses a BicycleTravelDisutility) + // compute and throw the additional score events: this.addEventHandlerBinding().to( BicycleScoreEventsCreator.class ); - // (the motorized interaction is in the BicycleScoreEventsCreator) + // (this uses the AdditionalBicycleLinkScore to compute and throw corresponding scoring events) + // (it also computes and throws the motorized interaction events, if they are switched on) this.bind( AdditionalBicycleLinkScore.class ).to( AdditionalBicycleLinkScoreDefaultImpl.class ); - - bind( BicycleLinkSpeedCalculator.class ).to( BicycleLinkSpeedCalculatorDefaultImpl.class ) ; - // this is still needed because the bicycle travel time calculator for routing needs to use the same bicycle speed as the mobsim. kai, jun'23 + // (this computes the value of the per-link scoring event. yyyy Very unfortunately, it is a re-implementation of the BicycleTravelDisutility (mentioned above).) this.installOverridingQSimModule( new AbstractQSimModule(){ @Override protected void configureQSim(){ @@ -65,6 +73,9 @@ public void install() { } } ); + bind( BicycleLinkSpeedCalculator.class ).to( BicycleLinkSpeedCalculatorDefaultImpl.class ) ; + // (both the router and the mobsim need this) + addControlerListenerBinding().to(ConsistencyCheck.class); } @@ -73,7 +84,6 @@ static class ConsistencyCheck implements StartupListener { @Inject private Scenario scenario; @Override public void notifyStartup(StartupEvent event) { - Id bicycleVehTypeId = Id.create(bicycleConfigGroup.getBicycleMode(), VehicleType.class); if (scenario.getVehicles().getVehicleTypes().get(bicycleVehTypeId) == null) { LOG.warn("There is no vehicle type '" + bicycleConfigGroup.getBicycleMode() + "' specified in the vehicle types. " diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleTravelDisutilityFactory.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleTravelDisutilityFactory.java index 135bc7e011f..ab7ffad85ad 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleTravelDisutilityFactory.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleTravelDisutilityFactory.java @@ -21,6 +21,8 @@ import com.google.inject.Inject; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.router.costcalculators.TravelDisutilityFactory; @@ -35,21 +37,20 @@ */ public final class BicycleTravelDisutilityFactory implements TravelDisutilityFactory { // public-final is ok since ctor is package-private: can only be used through injection - private static final Logger LOG = LogManager.getLogger(BicycleTravelDisutilityFactory.class); - - @Inject BicycleConfigGroup bicycleConfigGroup; - @Inject - ScoringConfigGroup cnScoringGroup; - @Inject - RoutingConfigGroup routingConfigGroup; - + private BicycleConfigGroup bicycleConfigGroup; + @Inject Config config; + @Inject ScoringConfigGroup cnScoringGroup; + @Inject RoutingConfigGroup routingConfigGroup; private static int normalisationWrnCnt = 0; - /* package-private */ BicycleTravelDisutilityFactory(){} + /* package-private */ BicycleTravelDisutilityFactory(){ + } @Override public TravelDisutility createTravelDisutility(TravelTime timeCalculator) { + this.bicycleConfigGroup = ConfigUtils.addOrGetModule( config, BicycleConfigGroup.class ); + double sigma = routingConfigGroup.getRoutingRandomness(); double normalization = 1; diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleUtils.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleUtils.java index 43bf5e63776..3af954d9c70 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleUtils.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleUtils.java @@ -127,4 +127,11 @@ private static boolean hasNoCycleway( String cyclewayType ) { } return userDefinedNetworkAttributeFactor; } + // === + public static void setSmoothness( Link link, String smoothness ){ + link.getAttributes().putAttribute( SMOOTHNESS, smoothness ); + } + public static void setBicycleInfrastructureFactor( Link link, double factor ){ + link.getAttributes().putAttribute( BICYCLE_INFRASTRUCTURE_SPEED_FACTOR, factor ); + } } diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/network/BicycleOsmNetworkReaderV2.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/network/BicycleOsmNetworkReaderV2.java index cd51b40275b..549f4c25656 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/network/BicycleOsmNetworkReaderV2.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/network/BicycleOsmNetworkReaderV2.java @@ -225,7 +225,7 @@ protected void setOrModifyLinkAttributes(Link l, OsmWay way, boolean forwardDire // Smoothness String smoothness = way.tags.get(BicycleUtils.SMOOTHNESS); if (smoothness != null) { - l.getAttributes().putAttribute(BicycleUtils.SMOOTHNESS, smoothness); + BicycleUtils.setSmoothness( l, smoothness ); this.countSmoothness++; } diff --git a/matsim/src/main/java/org/matsim/core/controler/ControlerDefaultsModule.java b/matsim/src/main/java/org/matsim/core/controler/ControlerDefaultsModule.java index fc5c43da358..293ac9ed415 100755 --- a/matsim/src/main/java/org/matsim/core/controler/ControlerDefaultsModule.java +++ b/matsim/src/main/java/org/matsim/core/controler/ControlerDefaultsModule.java @@ -85,8 +85,7 @@ public void install() { // Maybe not the best place to but this but since ChartUtils is used by many modules, including default ones, // the cache needs to be always set correctly. addControlerListenerBinding().toInstance(new StartupListener() { - @Inject - private OutputDirectoryHierarchy outputDirectoryHierarchy; + @Inject private OutputDirectoryHierarchy outputDirectoryHierarchy; @Override public void notifyStartup(StartupEvent event) { ImageIO.setCacheDirectory(new File(outputDirectoryHierarchy.getTempPath())); } diff --git a/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/AbstractAgentSnapshotInfoBuilder.java b/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/AbstractAgentSnapshotInfoBuilder.java index 78d2b0afe5d..c6bf2e47d49 100644 --- a/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/AbstractAgentSnapshotInfoBuilder.java +++ b/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/AbstractAgentSnapshotInfoBuilder.java @@ -139,12 +139,13 @@ public final void positionAgentGivenDistanceFromFNode(final Collection positionVehiclesAlongLine(Collection positions, - double now, Collection vehs, double curvedLength, double storageCapacity, - Coord upstreamCoord, Coord downstreamCoord, double inverseFlowCapPerTS, double freeSpeed, - int numberOfLanesAsInt, Queue holes) + public final Collection positionVehiclesAlongLine( Collection positions, + double now, Collection vehs, double curvedLength, double storageCapacity, + Coord upstreamCoord, Coord downstreamCoord, double inverseFlowCapPerTS, double freeSpeed, + int numberOfLanesAsInt, Queue holes, AbstractQLink.QLinkInternalInterface qLinkInternalInterface ) { double spacingOfOnePCE = this.calculateVehicleSpacing( curvedLength, storageCapacity, vehs ); + // ("vehs" is needed since the link may be more than full because of squeezing. In this case, spacingOfOnePCE is smaller than one "cell".) double ttimeOfHoles = curvedLength / (QueueWithBuffer.HOLE_SPEED_KM_H*1000./3600.); @@ -211,8 +212,16 @@ public final Collection positionVehiclesAlongLine(Collection< // (starts off relatively small (rightmost vehicle)) final double vehicleSpacing = mveh.getSizeInEquivalents() * spacingOfOnePCE; + + double speed = min( freeSpeed, veh.getMaximumVelocity() ); + if ( qLinkInternalInterface!=null ){ + speed = qLinkInternalInterface.getMaximumVelocityFromLinkSpeedCalculator( veh, now ); + } + distanceFromFromNode = this.calculateOdometerDistanceFromFromNode( - now, curvedLength, min( freeSpeed, veh.getMaximumVelocity()), vehicleSpacing, distanceFromFromNode, remainingTravelTime + now, curvedLength, + speed, // min( freeSpeed, veh.getMaximumVelocity()), + vehicleSpacing, distanceFromFromNode, remainingTravelTime ); // yyyy if the LinkSpeedCalculator says something that is not free speed, we are out of luck here. kai, jan'23 diff --git a/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueWithBuffer.java b/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueWithBuffer.java index 868e9813c65..741763e4c87 100644 --- a/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueWithBuffer.java +++ b/matsim/src/main/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueWithBuffer.java @@ -162,7 +162,7 @@ private void addValue(double value1, double now) { * pointer, and give access only to reduced number of methods (in particular not the full Link information). kai, feb'18 * This is now done with the {@link AbstractQLink.QLinkInternalInterface}. kai, feb'18 */ - private final AbstractQLink.QLinkInternalInterface qLink; + private final AbstractQLink.QLinkInternalInterface qLinkInternalInterface; private final Id id; private static int spaceCapWarningCount = 0; final static double HOLE_SPEED_KM_H = 15.0; @@ -202,7 +202,7 @@ private QueueWithBuffer(AbstractQLink.QLinkInternalInterface qlink, final Vehicl // log.setLevel(Level.DEBUG); this.flowEfficiencyCalculator = flowEfficiencyCalculator; - this.qLink = qlink; + this.qLinkInternalInterface = qlink; this.id = laneId ; this.context = context ; this.vehQueue = vehicleQueue ; @@ -239,7 +239,7 @@ private void addToBuffer(final QVehicle veh) { // need to reset the lastMovedTime. If, in contrast, there was already a vehicle in the buffer before, we can // use the lastMovedTime that was (somehow) computed for that vehicle.) } - final QNodeI toNode = qLink.getToNodeQ(); + final QNodeI toNode = qLinkInternalInterface.getToNodeQ(); if ( toNode instanceof AbstractQNode ) { ((AbstractQNode) toNode).activateNode(); // yy for an "upstream" QLane, this activates the toNode too early. Yet I think I founds this @@ -266,9 +266,9 @@ private void moveQueueToBuffer() { MobsimDriverAgent driver = veh.getDriver(); if (driver instanceof TransitDriverAgent) { - HandleTransitStopResult handleTransitStop = qLink.handleTransitStop( - now, veh, (TransitDriverAgent) driver, this.qLink.getId() - ); + HandleTransitStopResult handleTransitStop = qLinkInternalInterface.handleTransitStop( + now, veh, (TransitDriverAgent) driver, this.qLinkInternalInterface.getId() + ); if (handleTransitStop == HandleTransitStopResult.accepted) { // vehicle has been accepted into the transit vehicle queue of the link. removeVehicleFromQueue(veh); @@ -285,7 +285,7 @@ private void moveQueueToBuffer() { // Check if veh has reached destination: if (driver.isWantingToArriveOnCurrentLink()) { - if (qLink.letVehicleArrive(veh)) { + if ( qLinkInternalInterface.letVehicleArrive(veh )) { // remove _after_ processing the arrival to keep link active: removeVehicleFromQueue(veh); continue; @@ -395,8 +395,8 @@ private void calculateFlowCapacity() { // yyyyyy this should possibly be getFreespeed(now). But if that's the case, then maxFlowFromFdiag would // also have to be re-computed with each freespeed change. kai, feb'18 - final double maxFlowFromFdiag = (this.effectiveNumberOfLanes/context.effectiveCellSize) / ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLink.getFreespeed() ) ; - final double minimumNumberOfLanesFromFdiag = this.flowCapacityPerTimeStep * context.effectiveCellSize * ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLink.getFreespeed() ); + final double maxFlowFromFdiag = (this.effectiveNumberOfLanes/context.effectiveCellSize) / ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLinkInternalInterface.getFreespeed() ) ; + final double minimumNumberOfLanesFromFdiag = this.flowCapacityPerTimeStep * context.effectiveCellSize * ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLinkInternalInterface.getFreespeed() ); QSimConfigGroup.InflowCapacitySetting inflowCapacitySetting = context.qsimConfig.getInflowCapacitySetting(); @@ -411,19 +411,19 @@ private void calculateFlowCapacity() { log.warn( Gbl.FUTURE_SUPPRESSED ) ; } - this.maxInflowUsedInQsim = (1/context.effectiveCellSize) / ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLink.getFreespeed() ) ; + this.maxInflowUsedInQsim = (1/context.effectiveCellSize) / ( 1./(HOLE_SPEED_KM_H/3.6) + 1/this.qLinkInternalInterface.getFreespeed() ) ; // write out the modified qsim behavior as link attribute - qLink.getLink().getAttributes().putAttribute("maxInflowUsedInQsim", 3600* maxInflowUsedInQsim /context.qsimConfig.getTimeStepSize()); + qLinkInternalInterface.getLink().getAttributes().putAttribute("maxInflowUsedInQsim", 3600* maxInflowUsedInQsim /context.qsimConfig.getTimeStepSize() ); } else { if ( maxFlowFromFdiag < flowCapacityPerTimeStep ){ //warnings if (wrnCnt<10) { wrnCnt++ ; - log.warn( "max flow from fdiag < flow cap in network file; linkId=" + qLink.getId() + + log.warn( "max flow from fdiag < flow cap in network file; linkId=" + qLinkInternalInterface.getId() + "; network file flow cap/h=" + 3600.*flowCapacityPerTimeStep/context.qsimConfig.getTimeStepSize() + "; max flow from fdiag/h=" + 3600*maxFlowFromFdiag/context.qsimConfig.getTimeStepSize() ) ; - log.warn( "number of lanes from fdiag > number of lanes in network file; linkId=" + qLink.getId() + + log.warn( "number of lanes from fdiag > number of lanes in network file; linkId=" + qLinkInternalInterface.getId() + "; number of lanes in network file=" + this.effectiveNumberOfLanes + "; number of lanes from fdiag=" + minimumNumberOfLanesFromFdiag ) ; @@ -445,11 +445,11 @@ private void calculateFlowCapacity() { if (inflowCapacitySetting == QSimConfigGroup.InflowCapacitySetting.INFLOW_FROM_FDIAG) { this.maxInflowUsedInQsim = maxFlowFromFdiag; // write out the modified qsim behavior as link attribute - qLink.getLink().getAttributes().putAttribute("maxInflowUsedInQsim", 3600* maxInflowUsedInQsim /context.qsimConfig.getTimeStepSize()); + qLinkInternalInterface.getLink().getAttributes().putAttribute("maxInflowUsedInQsim", 3600* maxInflowUsedInQsim /context.qsimConfig.getTimeStepSize() ); } else if (inflowCapacitySetting == QSimConfigGroup.InflowCapacitySetting.NR_OF_LANES_FROM_FDIAG) { this.effectiveNumberOfLanesUsedInQsim = minimumNumberOfLanesFromFdiag; // write out the modified qsim behavior as link attribute - qLink.getLink().getAttributes().putAttribute("effectiveNumberOfLanesUsedInQsim", effectiveNumberOfLanesUsedInQsim); + qLinkInternalInterface.getLink().getAttributes().putAttribute("effectiveNumberOfLanesUsedInQsim", effectiveNumberOfLanesUsedInQsim ); } else { throw new RuntimeException("The approach "+ inflowCapacitySetting.toString()+" is not implemented yet."); } @@ -483,7 +483,7 @@ private void calculateStorageCapacity() { * Will base these computations (for the time being) on the standard free speed; i.e. reductions in free speed * will also reduce the maximum flow. */ - double freespeedTravelTime = this.length / qLink.getFreespeed(); + double freespeedTravelTime = this.length / qLinkInternalInterface.getFreespeed(); // yyyyyy this should possibly be getFreespeed(now). But if that's the case, then storageCap would // also have to be re-computed with each freespeed change. kai, feb'18 if (Double.isNaN(freespeedTravelTime)) { @@ -507,7 +507,7 @@ private void calculateStorageCapacity() { storageCapacity = tempStorageCapacity; // write out the modified qsim behavior as link attribute - qLink.getLink().getAttributes().putAttribute("storageCapacityUsedInQsim", storageCapacity); + qLinkInternalInterface.getLink().getAttributes().putAttribute("storageCapacityUsedInQsim", storageCapacity ); } /* About minStorCapForHoles: @@ -527,7 +527,7 @@ private void calculateStorageCapacity() { case withHoles: case kinematicWaves: // final double minStorCapForHoles = 2. * flowCapacityPerTimeStep * context.getSimTimer().getSimTimestepSize(); - final double freeSpeed = qLink.getFreespeed() ; // yyyyyy not clear why this is not time-dep. kai, feb'18 + final double freeSpeed = qLinkInternalInterface.getFreespeed() ; // yyyyyy not clear why this is not time-dep. kai, feb'18 final double holeSpeed = HOLE_SPEED_KM_H/3.6; final double minStorCapForHoles = length * flowCapacityPerTimeStep * (freeSpeed + holeSpeed) / freeSpeed / holeSpeed ; // final double minStorCapForHoles = 2.* length * flowCapacityPerTimeStep * (freeSpeed + holeSpeed) / freeSpeed / holeSpeed ; @@ -541,7 +541,7 @@ private void calculateStorageCapacity() { } storageCapacity = minStorCapForHoles ; // write out the modified qsim behavior as link attribute - qLink.getLink().getAttributes().putAttribute("storageCapacityUsedInQsim", storageCapacity); + qLinkInternalInterface.getLink().getAttributes().putAttribute("storageCapacityUsedInQsim", storageCapacity ); } remainingHolesStorageCapacity = this.storageCapacity; @@ -589,12 +589,12 @@ public final void addFromUpstream(final QVehicle veh) { if (this.context.qsimConfig.isUseLanes()) { if (hasMoreThanOneLane()) { - this.context.getEventsManager().processEvent(new LaneEnterEvent(now, veh.getId(), this.qLink.getId(), this.getId())); + this.context.getEventsManager().processEvent(new LaneEnterEvent(now, veh.getId(), this.qLinkInternalInterface.getId(), this.getId()) ); } } // activate link since there is now action on it: - qLink.activateLink(); + qLinkInternalInterface.activateLink(); if (context.qsimConfig.isSeepModeStorageFree() && context.qsimConfig.getSeepModes().contains(veh.getVehicle().getType().getId().toString())) { // do nothing @@ -604,7 +604,7 @@ public final void addFromUpstream(final QVehicle veh) { // compute and set earliest link exit time: // double linkTravelTime = this.length / this.linkSpeedCalculator.getMaximumVelocity(veh, qLink.getLink(), now); - double linkTravelTime = this.length / this.qLink.getMaximumVelocityFromLinkSpeedCalculator(veh, now); + double linkTravelTime = this.length / this.qLinkInternalInterface.getMaximumVelocityFromLinkSpeedCalculator(veh, now ); linkTravelTime = context.qsimConfig.getTimeStepSize() * Math.floor(linkTravelTime / context.qsimConfig.getTimeStepSize()); veh.setEarliestLinkExitTime(now + linkTravelTime); @@ -619,7 +619,7 @@ public final void addFromUpstream(final QVehicle veh) { // inserted and thus end up after vehicles with a later link exit time. theresa & kai, jun'14 // veh.setCurrentLink(qLink.getLink()); - this.qLink.setCurrentLinkToVehicle(veh); + this.qLinkInternalInterface.setCurrentLinkToVehicle(veh ); vehQueue.add(veh); switch (context.qsimConfig.getTrafficDynamics()) { @@ -795,7 +795,7 @@ public final QVehicle popFirstVehicle() { QVehicle veh = removeFirstVehicle(); if (this.context.qsimConfig.isUseLanes() ) { if ( hasMoreThanOneLane() ) { - this.context.getEventsManager().processEvent(new LaneLeaveEvent( now, veh.getId(), this.qLink.getId(), this.getId() )); + this.context.getEventsManager().processEvent(new LaneLeaveEvent( now, veh.getId(), this.qLinkInternalInterface.getId(), this.getId() ) ); } } return veh; @@ -813,7 +813,7 @@ private final QVehicle removeFirstVehicle(){ @Override public final void setSignalStateForTurningMove( final SignalGroupState state, final Id toLinkId) { - if (!qLink.getToNode().getOutLinks().containsKey(toLinkId)){ + if (!qLinkInternalInterface.getToNode().getOutLinks().containsKey(toLinkId )){ throw new IllegalArgumentException("ToLink " + toLinkId + " is not reachable from QLink Id " + this.id ); } qSignalizedItem.setSignalStateForTurningMove(state, toLinkId); @@ -879,12 +879,12 @@ public final void clearVehicles() { } private double getFlowCapacityConsumptionInEquivalents(QVehicle vehicle, QVehicle prevVehicle, Double timeDiff) { - double flowEfficiency = flowEfficiencyCalculator.calculateFlowEfficiency(vehicle, prevVehicle, timeDiff, qLink.getLink(), id); + double flowEfficiency = flowEfficiencyCalculator.calculateFlowEfficiency(vehicle, prevVehicle, timeDiff, qLinkInternalInterface.getLink(), id ); return vehicle.getSizeInEquivalents() / flowEfficiency; } private boolean hasMoreThanOneLane() { - return this.qLink.getAcceptingQLane() != this.qLink.getOfferingQLanes().get(0); + return this.qLinkInternalInterface.getAcceptingQLane() != this.qLinkInternalInterface.getOfferingQLanes().get(0 ); // this works independent from sorting since if there is only one lane, then it has to be the one to be returned by // getOfferingQLanes().get(0), and it is also the same as the accepting QLane. If, however, "lanes" is used, // there are at least two lanes in sequence, so the accepting lane is never the same as any of the offering lanes, and @@ -919,7 +919,7 @@ public final void addTransitSlightlyUpstreamOfStop( final QVehicle veh) { @Override public final void setSignalized( final boolean isSignalized) { - qSignalizedItem = new DefaultSignalizeableItem(qLink.getToNode().getOutLinks().keySet()); + qSignalizedItem = new DefaultSignalizeableItem( qLinkInternalInterface.getToNode().getOutLinks().keySet()); } @Override @@ -989,10 +989,10 @@ public final Collection addAgentSnapshotInfo(Collection addAgentSnapshotInfo(Collection() - ); + new LinkedList<>(), + null ); // assert assertEquals(1, outCollection.size()); @@ -85,8 +85,8 @@ void positionVehiclesAlongLine_congestedAboveCapacityLimit() { 1 / setUp.linkCapacity, // this would mean the flow capacity is 100 setUp.freespeed, 1, - new LinkedList<>() - ); + new LinkedList<>(), + null ); // assert assertEquals(vehicles.size(), outCollection.size()); @@ -337,4 +337,4 @@ private static Collection createAgents(int size) { return result; } -} \ No newline at end of file +} diff --git a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueAgentSnapshotInfoBuilderTest.java b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueAgentSnapshotInfoBuilderTest.java index b81a8fb91a0..b815ced0819 100644 --- a/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueAgentSnapshotInfoBuilderTest.java +++ b/matsim/src/test/java/org/matsim/core/mobsim/qsim/qnetsimengine/QueueAgentSnapshotInfoBuilderTest.java @@ -53,8 +53,8 @@ void positionVehiclesAlongLine_singleVehicleFreeFlow() { 1 / setUp.linkCapacity, // this would mean the flow capacity is 100 setUp.freespeed, 1, - new LinkedList<>() - ); + new LinkedList<>(), + null ); // assert assertEquals(1, outCollection.size()); @@ -94,8 +94,8 @@ void positionVehiclesAlongLine_congestedAboveCapacityLimit() { 1 / setUp.linkCapacity, // this would mean the flow capacity is 100 setUp.freespeed, 1, - new LinkedList<>() - ); + new LinkedList<>(), + null ); // assert assertEquals(vehicles.size(), outCollection.size()); @@ -132,8 +132,8 @@ void positionVehiclesAlongLine_queueAtEnd() { 1 / setUp.linkCapacity, setUp.freespeed, 1, - new LinkedList<>() - ); + new LinkedList<>(), + null ); // assert assertEquals(5, outCollection.size()); @@ -473,4 +473,4 @@ private static Collection createAgents(int size) { } return result; } -} \ No newline at end of file +} From 7b0e554550586153cf2a8c42f286b8fa34e6f89e Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Thu, 4 Jul 2024 18:37:46 +0200 Subject: [PATCH 2/2] repair test failures --- .../org/matsim/contrib/bicycle/BicycleModule.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java index 45e03c8a2f9..030a54935f5 100644 --- a/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java +++ b/contribs/bicycle/src/main/java/org/matsim/contrib/bicycle/BicycleModule.java @@ -40,13 +40,20 @@ public final class BicycleModule extends AbstractModule { private static final Logger LOG = LogManager.getLogger(BicycleModule.class); + @Inject private BicycleConfigGroup bicycleConfigGroup; + @Override public void install() { - BicycleConfigGroup bicycleConfigGroup = ConfigUtils.addOrGetModule( this.getConfig(), BicycleConfigGroup.class ); - this.bind( BicycleConfigGroup.class ).toInstance( bicycleConfigGroup ); +// BicycleConfigGroup bicycleConfigGroup = ConfigUtils.addOrGetModule( this.getConfig(), BicycleConfigGroup.class ); +// this.bind( BicycleConfigGroup.class ).toInstance( bicycleConfigGroup ); // the above feels odd. But it seems to work. I actually have no idea where the config groups are bound, neither for the core config // groups nor for the added config groups. In general, the original idea was that AbstractModule provides the config from // getConfig(), not from injection. kai, jun'24 + // It actually does not work in general. The ExplodedConfigModule injects all config groups that are materialized by then. Which + // means that it needs to be materialized "quite early", and in particular before this install method is called. For the time being, + // a run script using the contrib thus needs to materialize the config group. kai, jul'24 + + // The idea here is the following: // * scores are just added as score events. no scoring function is replaced.