diff --git a/contribs/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java b/contribs/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java index 9ff85eb7b67..35f11ab09d6 100644 --- a/contribs/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java +++ b/contribs/application/src/main/java/org/matsim/application/analysis/population/TripAnalysis.java @@ -92,6 +92,7 @@ public Integer call() throws Exception { Table persons = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(input.getPath("persons.csv"))) .columnTypesPartial(Map.of("person", ColumnType.TEXT)) + .sample(false) .separator(';').build()); int total = persons.rowCount(); @@ -132,6 +133,7 @@ public Integer call() throws Exception { Table trips = Table.read().csv(CsvReadOptions.builder(IOUtils.getBufferedReader(input.getPath("trips.csv"))) .columnTypesPartial(columnTypes) + .sample(false) .separator(';').build()); diff --git a/contribs/discrete_mode_choice/src/test/java/org/matsim/contrib/discrete_mode_choice/examples/TestSiouxFalls.java b/contribs/discrete_mode_choice/src/test/java/org/matsim/contrib/discrete_mode_choice/examples/TestSiouxFalls.java index 59e3cf6d1a4..7b71a32670e 100644 --- a/contribs/discrete_mode_choice/src/test/java/org/matsim/contrib/discrete_mode_choice/examples/TestSiouxFalls.java +++ b/contribs/discrete_mode_choice/src/test/java/org/matsim/contrib/discrete_mode_choice/examples/TestSiouxFalls.java @@ -61,9 +61,9 @@ public void install() { System.out.println((int) listener.counts.get("car")); System.out.println(listener.counts.get("walk")); - assertEquals(44195, (int) listener.counts.get("pt")); - assertEquals(132316, (int) listener.counts.get("car")); - assertEquals(82139, (int) listener.counts.get("walk")); + assertEquals(44195, listener.counts.get("pt"), 2); + assertEquals(132316, listener.counts.get("car"), 2); + assertEquals(82139, listener.counts.get("walk"), 2); } diff --git a/contribs/drt-extensions/pom.xml b/contribs/drt-extensions/pom.xml index b56ab569782..2217f9ebdc7 100644 --- a/contribs/drt-extensions/pom.xml +++ b/contribs/drt-extensions/pom.xml @@ -24,6 +24,12 @@ 16.0-SNAPSHOT + + org.matsim.contrib + informed-mode-choice + 16.0-SNAPSHOT + + org.matsim.contrib simwrapper @@ -33,6 +39,7 @@ org.assertj assertj-core + test diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java index 6239ca5a240..d84aa00e156 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java @@ -60,7 +60,7 @@ import org.matsim.contrib.dvrp.schedule.ScheduleTimingUpdater; import org.matsim.contrib.dvrp.vrpagent.VrpAgentLogic; import org.matsim.contrib.ev.infrastructure.ChargingInfrastructure; -import org.matsim.contrib.ev.infrastructure.ChargingInfrastructures; +import org.matsim.contrib.ev.infrastructure.ChargingInfrastructureUtils; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.mobsim.framework.MobsimTimer; import org.matsim.core.modal.ModalProviders; @@ -95,8 +95,8 @@ protected void configureQSim() { getter.getModal(DrtRequestInsertionRetryQueue.class)))).asEagerSingleton(); bindModal(ChargingInfrastructure.class).toProvider(modalProvider( - getter -> ChargingInfrastructures.createModalNetworkChargers(getter.get(ChargingInfrastructure.class), - getter.getModal(Network.class), getMode()))).asEagerSingleton(); + getter -> ChargingInfrastructureUtils.createModalNetworkChargers(getter.get(ChargingInfrastructure.class ), + getter.getModal(Network.class), getMode() ))).asEagerSingleton(); // XXX if overridden to something else, make sure that the depots are equipped with chargers // otherwise vehicles will not re-charge diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/BasicDrtEstimator.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/BasicDrtEstimator.java new file mode 100644 index 00000000000..3d7555020e1 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/BasicDrtEstimator.java @@ -0,0 +1,172 @@ +package org.matsim.contrib.drt.extension.estimator; + +import org.apache.commons.math3.stat.descriptive.SummaryStatistics; +import org.apache.commons.math3.stat.regression.RegressionResults; +import org.apache.commons.math3.stat.regression.SimpleRegression; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.events.PersonMoneyEvent; +import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector; +import org.matsim.contrib.drt.extension.estimator.run.DrtEstimatorConfigGroup; +import org.matsim.contrib.drt.fare.DrtFareParams; +import org.matsim.contrib.drt.routing.DrtRoute; +import org.matsim.contrib.drt.run.DrtConfigGroup; +import org.matsim.contrib.drt.speedup.DrtSpeedUp; +import org.matsim.core.controler.events.IterationEndsEvent; +import org.matsim.core.controler.listener.IterationEndsListener; +import org.matsim.core.utils.misc.OptionalTime; + +import java.util.SplittableRandom; + +/** + * Estimates drt trips based only daily averages. No spatial or temporal differentiation is taken into account for the estimate. + * This estimator is suited for small scenarios with few vehicles and trips and consequently few data points. + */ +public class BasicDrtEstimator implements DrtEstimator, IterationEndsListener { + + private static final Logger log = LogManager.getLogger(BasicDrtEstimator.class); + + private final DrtEventSequenceCollector collector; + private final DrtEstimatorConfigGroup config; + private final DrtConfigGroup drtConfig; + + private final SplittableRandom rnd = new SplittableRandom(); + /** + * Currently valid estimates. + */ + private GlobalEstimate currentEst; + private RegressionResults fare; + + public BasicDrtEstimator(DrtEventSequenceCollector collector, DrtEstimatorConfigGroup config, + DrtConfigGroup drtConfig) { + //zones = injector.getModal(DrtZonalSystem.class); + this.collector = collector; + this.config = config; + this.drtConfig = drtConfig; + } + + @Override + public void notifyIterationEnds(IterationEndsEvent event) { + + // Speed-up iteration need to be ignored for the estimates + if (drtConfig.getDrtSpeedUpParams().isPresent() && + DrtSpeedUp.isTeleportDrtUsers(drtConfig.getDrtSpeedUpParams().get(), + event.getServices().getConfig().controller(), event.getIteration())) { + return; + } + + GlobalEstimate est = new GlobalEstimate(); + + int n = 0; + + int nRejections = collector.getRejectedRequestSequences().size(); + int nSubmitted = collector.getRequestSubmissions().size(); + + for (DrtEventSequenceCollector.EventSequence seq : collector.getPerformedRequestSequences().values()) { + + if (seq.getPickedUp().isPresent() && seq.getDroppedOff().isPresent()) { + + double waitTime = seq.getPickedUp().get().getTime() - seq.getSubmitted().getTime(); + est.waitTime.addValue(waitTime); + + double unsharedTime = seq.getSubmitted().getUnsharedRideTime(); + double travelTime = seq.getDroppedOff().get().getTime() - seq.getPickedUp().get().getTime(); + + est.detour.addValue(travelTime / unsharedTime); + + double fare = seq.getDrtFares().stream().mapToDouble(PersonMoneyEvent::getAmount).sum(); + est.fare.addData(seq.getSubmitted().getUnsharedRideDistance(), fare); + n++; + } + } + + // At least some data points are required + if (n <= 3) + return; + + fare = est.fare.regress(); + + double rejectionRate = (double) nRejections / nSubmitted; + + if (currentEst == null) { + est.meanWait = est.waitTime.getMean(); + est.stdWait = est.waitTime.getStandardDeviation(); + est.meanDetour = est.detour.getMean(); + est.stdDetour = est.detour.getStandardDeviation(); + est.rejectionRate = rejectionRate; + } else { + est.meanWait = config.decayFactor * est.waitTime.getMean() + (1 - config.decayFactor) * currentEst.waitTime.getMean(); + est.stdWait = config.decayFactor * est.waitTime.getStandardDeviation() + (1 - config.decayFactor) * currentEst.waitTime.getStandardDeviation(); + est.meanDetour = config.decayFactor * est.detour.getMean() + (1 - config.decayFactor) * currentEst.detour.getMean(); + est.stdDetour = config.decayFactor * est.detour.getStandardDeviation() + (1 - config.decayFactor) * currentEst.detour.getStandardDeviation(); + est.rejectionRate = config.decayFactor * rejectionRate + (1 - config.decayFactor) * currentEst.rejectionRate; + } + + log.info("Calculated {}", est); + currentEst = est; + } + + @Override + public Estimate estimate(DrtRoute route, OptionalTime departureTime) { + + if (currentEst == null) { + // If not estimates are present, use travel time alpha as detour + // beta is not used, because estimates are supposed to be minimums and not worst cases + double travelTime = Math.min(route.getDirectRideTime() + drtConfig.maxAbsoluteDetour, + route.getDirectRideTime() * drtConfig.maxTravelTimeAlpha); + + double fare = 0; + if (drtConfig.getDrtFareParams().isPresent()) { + DrtFareParams fareParams = drtConfig.getDrtFareParams().get(); + fare = fareParams.distanceFare_m * route.getDistance() + + fareParams.timeFare_h * route.getDirectRideTime() / 3600.0 + + fareParams.baseFare; + + fare = Math.max(fare, fareParams.minFarePerTrip); + } + + // for distance, also use the max travel time alpha + return new Estimate(route.getDistance() * drtConfig.maxTravelTimeAlpha, travelTime, drtConfig.maxWaitTime, fare, 0); + } + + double fare = 0; + if (this.fare != null) + fare = this.fare.getParameterEstimate(0) + this.fare.getParameterEstimate(1) * route.getDistance(); + + if (drtConfig.getDrtFareParams().isPresent()) { + fare = Math.max(fare, drtConfig.getDrtFareParams().get().minFarePerTrip); + } + + double detour = Math.max(1, rnd.nextGaussian(currentEst.meanDetour, config.randomization * currentEst.stdDetour)); + double waitTime = Math.max(0, rnd.nextGaussian(currentEst.meanWait, config.randomization * currentEst.stdWait)); + + return new Estimate(route.getDistance() * detour, route.getDirectRideTime() * detour, waitTime, fare, currentEst.rejectionRate); + } + + /** + * Helper class to hold statistics. + */ + private static final class GlobalEstimate { + + private final SummaryStatistics waitTime = new SummaryStatistics(); + private final SummaryStatistics detour = new SummaryStatistics(); + private final SimpleRegression fare = new SimpleRegression(true); + + private double meanWait; + private double stdWait; + private double meanDetour; + private double stdDetour; + private double rejectionRate; + + @Override + public String toString() { + return "GlobalEstimate{" + + "meanWait=" + meanWait + + ", stdWait=" + stdWait + + ", meanDetour=" + meanDetour + + ", stdDetour=" + stdDetour + + ", rejectionRate=" + rejectionRate + + '}'; + } + } +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/DrtEstimateAnalyzer.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/DrtEstimateAnalyzer.java new file mode 100644 index 00000000000..2d87f7ea7b8 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/DrtEstimateAnalyzer.java @@ -0,0 +1,126 @@ +package org.matsim.contrib.drt.extension.estimator; + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.events.PersonMoneyEvent; +import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector; +import org.matsim.contrib.drt.extension.estimator.run.DrtEstimatorConfigGroup; +import org.matsim.contrib.drt.routing.DrtRoute; +import org.matsim.core.controler.events.AfterMobsimEvent; +import org.matsim.core.controler.events.ShutdownEvent; +import org.matsim.core.controler.events.StartupEvent; +import org.matsim.core.controler.listener.AfterMobsimListener; +import org.matsim.core.controler.listener.ShutdownListener; +import org.matsim.core.controler.listener.StartupListener; +import org.matsim.core.utils.misc.OptionalTime; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +/** + * Analyzes and outputs drt estimates errors metrics based on daily requests. + */ +public final class DrtEstimateAnalyzer implements StartupListener, ShutdownListener, AfterMobsimListener { + + private static final Logger log = LogManager.getLogger(DrtEstimateAnalyzer.class); + + // Might be useful but not needed currently + //private final DefaultMainLegRouter.RouteCreator creator; + private final DrtEstimator estimator; + private final DrtEventSequenceCollector collector; + private final DrtEstimatorConfigGroup config; + + private CSVPrinter csv; + + public DrtEstimateAnalyzer(DrtEstimator estimator, DrtEventSequenceCollector collector, DrtEstimatorConfigGroup config) { + this.estimator = estimator; + this.collector = collector; + this.config = config; + } + + @Override + public void notifyStartup(StartupEvent event) { + + String filename = event.getServices().getControlerIO().getOutputFilename("drt_estimates_" + config.getMode() + ".csv"); + + try { + csv = new CSVPrinter(Files.newBufferedWriter(Path.of(filename), StandardCharsets.UTF_8), CSVFormat.DEFAULT); + csv.printRecord("iteration", + "wait_time_mae", "wait_time_err_q5", "wait_time_err_q50", "wait_time_err_q95", + "travel_time_mae", "travel_time_err_q5", "travel_time_err_q50", "travel_time_err_q95", + "fare_mae", "fare_err_q5", "fare_err_q50", "fare_err_q95" + ); + + } catch (IOException e) { + throw new UncheckedIOException("Could not open output file for estimates.", e); + } + } + + @Override + public void notifyShutdown(ShutdownEvent event) { + try { + csv.close(); + } catch (IOException e) { + log.warn("Could not close drt estimate file", e); + } + } + + /** + * Needs to run before any estimators updates. + */ + @Override + public void notifyAfterMobsim(AfterMobsimEvent event) { + + try { + csv.printRecord(calcMetrics(event.getIteration())); + csv.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Return row of metrics for the csv file. + */ + private Iterable calcMetrics(int iteration) { + + DescriptiveStatistics waitTime = new DescriptiveStatistics(); + DescriptiveStatistics travelTime = new DescriptiveStatistics(); + DescriptiveStatistics fare = new DescriptiveStatistics(); + + for (DrtEventSequenceCollector.EventSequence seq : collector.getPerformedRequestSequences().values()) { + if (seq.getPickedUp().isPresent() && seq.getDroppedOff().isPresent()) { + + // many attributes are not filled, when using the constructor + DrtRoute route = new DrtRoute(seq.getSubmitted().getFromLinkId(), seq.getSubmitted().getToLinkId()); + route.setDirectRideTime(seq.getSubmitted().getUnsharedRideTime()); + route.setDistance(seq.getSubmitted().getUnsharedRideDistance()); + + double valWaitTime = seq.getPickedUp().get().getTime() - seq.getSubmitted().getTime(); + double valTravelTime = seq.getDroppedOff().get().getTime() - seq.getPickedUp().get().getTime(); + double valFare = seq.getDrtFares().stream().mapToDouble(PersonMoneyEvent::getAmount).sum(); + + DrtEstimator.Estimate estimate = estimator.estimate(route, OptionalTime.defined(seq.getSubmitted().getTime())); + + waitTime.addValue(Math.abs(estimate.waitingTime() - valWaitTime)); + travelTime.addValue(Math.abs(estimate.travelTime() - valTravelTime)); + fare.addValue(Math.abs(estimate.fare() - valFare)); + } + } + + return List.of( + iteration, + waitTime.getMean(), waitTime.getPercentile(5), waitTime.getPercentile(50), waitTime.getPercentile(95), + travelTime.getMean(), travelTime.getPercentile(5), travelTime.getPercentile(50), travelTime.getPercentile(95), + fare.getMean(), fare.getPercentile(5), fare.getPercentile(50), fare.getPercentile(95) + ); + } + +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/DrtEstimator.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/DrtEstimator.java new file mode 100644 index 00000000000..fef209ed211 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/DrtEstimator.java @@ -0,0 +1,35 @@ +package org.matsim.contrib.drt.extension.estimator; + +import org.matsim.contrib.drt.routing.DrtRoute; +import org.matsim.core.controler.listener.ControlerListener; +import org.matsim.core.utils.misc.OptionalTime; + +/** + * Interface to estimate a DRT service's detour, waiting time and costs. + */ +public interface DrtEstimator extends ControlerListener { + + /** + * Provide an estimate for a drt route with specific pickup and dropoff point. + * + * @param route drt route + * @param departureTime estimated departure time + * @return An {@link Estimate} instance + */ + Estimate estimate(DrtRoute route, OptionalTime departureTime); + + + /** + * Estimate for various attributes for a drt trip. + * + * @param distance travel distance in meter + * @param travelTime travel time in seconds + * @param waitingTime waiting time in seconds + * @param fare money, which is negative if the customer needs to pay it + * @param rejectionRate probability of a trip being rejected + */ + record Estimate(double distance, double travelTime, double waitingTime, double fare, double rejectionRate) { + + } + +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimator.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimator.java new file mode 100644 index 00000000000..ed1771ae34f --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimator.java @@ -0,0 +1,58 @@ +package org.matsim.contrib.drt.extension.estimator; + +import com.google.inject.Inject; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.population.Leg; +import org.matsim.contrib.drt.routing.DrtRoute; +import org.matsim.contrib.dvrp.run.DvrpMode; +import org.matsim.core.scoring.functions.ModeUtilityParameters; +import org.matsim.core.utils.misc.OptionalTime; +import org.matsim.modechoice.EstimatorContext; +import org.matsim.modechoice.ModeAvailability; +import org.matsim.modechoice.estimators.LegEstimator; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + + +/** + * Aggregate class for informed-mode-choice that makes sure to invoke the correct estimator for each drt mode. + */ +public class MultiModalDrtLegEstimator implements LegEstimator { + + private static final Logger log = LogManager.getLogger(MultiModalDrtLegEstimator.class); + + protected final Map estimators = new HashMap<>(); + + @Inject + public MultiModalDrtLegEstimator(Map estimators) { + for (Map.Entry e : estimators.entrySet()) { + this.estimators.put(e.getKey().value(), e.getValue()); + } + } + + @Override + public double estimate(EstimatorContext context, String mode, Leg leg, ModeAvailability option) { + + if (!(leg.getRoute() instanceof DrtRoute route)) + throw new IllegalStateException("Drt leg routes must be of type DrtRoute."); + + OptionalTime departureTime = leg.getDepartureTime(); + + DrtEstimator estimator = Objects.requireNonNull(estimators.get(mode), String.format("No drt estimator found for mode %s. Check warnings for errors.", mode)); + + DrtEstimator.Estimate est = estimator.estimate(route, departureTime); + ModeUtilityParameters params = context.scoring.modeParams.get(mode); + + // By default, waiting time is scored as travel time + return params.constant + + params.marginalUtilityOfDistance_m * est.distance() + + params.marginalUtilityOfTraveling_s * est.travelTime() + + params.marginalUtilityOfTraveling_s * est.waitingTime() + + context.scoring.marginalUtilityOfMoney * params.monetaryDistanceCostRate * est.distance() + + context.scoring.marginalUtilityOfMoney * est.fare(); + + } +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/run/DrtEstimatorConfigGroup.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/run/DrtEstimatorConfigGroup.java new file mode 100644 index 00000000000..107aa2eb53a --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/run/DrtEstimatorConfigGroup.java @@ -0,0 +1,61 @@ +package org.matsim.contrib.drt.extension.estimator.run; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.contrib.dvrp.run.Modal; +import org.matsim.contrib.util.ReflectiveConfigGroupWithConfigurableParameterSets; + +public class DrtEstimatorConfigGroup extends ReflectiveConfigGroupWithConfigurableParameterSets implements Modal { + + /** + * Type of estimator, which will be installed in {@link DrtEstimatorModule}. + */ + public enum EstimatorType { + BASIC, + + /** + * Custom estimator, that needs to provided via binding. + */ + CUSTOM + } + + public static final String GROUP_NAME = "drtEstimator"; + + public DrtEstimatorConfigGroup() { + super(GROUP_NAME); + } + + public DrtEstimatorConfigGroup(String mode) { + super(GROUP_NAME); + this.mode = mode; + } + + @Parameter + @Comment("Mode of the drt service to estimate.") + @NotBlank + public String mode = TransportMode.drt; + + @Parameter + @Comment("Estimator typed to be used. In case of 'CUSTOM', guice bindings needs to be provided.") + @NotNull + public EstimatorType estimator = EstimatorType.BASIC; + + @Parameter + @Comment("Decay of the exponential moving average.") + @Positive + public double decayFactor = 0.7; + + @Parameter + @Comment("Factor multiplied with standard deviation to randomize estimates.") + @PositiveOrZero + public double randomization = 0.1; + + @Override + public String getMode() { + return mode; + } + +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/run/DrtEstimatorModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/run/DrtEstimatorModule.java new file mode 100644 index 00000000000..14bc2ae330d --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/run/DrtEstimatorModule.java @@ -0,0 +1,80 @@ +package org.matsim.contrib.drt.extension.estimator.run; + +import com.google.inject.Singleton; +import com.google.inject.multibindings.MapBinder; +import org.matsim.contrib.drt.analysis.DrtEventSequenceCollector; +import org.matsim.contrib.drt.extension.estimator.BasicDrtEstimator; +import org.matsim.contrib.drt.extension.estimator.DrtEstimateAnalyzer; +import org.matsim.contrib.drt.extension.estimator.DrtEstimator; +import org.matsim.contrib.drt.run.DrtConfigGroup; +import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; +import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; +import org.matsim.contrib.dvrp.run.DvrpMode; +import org.matsim.contrib.dvrp.run.DvrpModes; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.AbstractModule; + +import java.util.Optional; + +/** + * Main module that needs to be installed if any estimator is to be used. + */ +public class DrtEstimatorModule extends AbstractModule { + + @Override + public void install() { + + MultiModeDrtConfigGroup drtConfigs = MultiModeDrtConfigGroup.get(getConfig()); + MultiModeDrtEstimatorConfigGroup configs = ConfigUtils.addOrGetModule(getConfig(), MultiModeDrtEstimatorConfigGroup.class); + + for (DrtConfigGroup cfg : drtConfigs.getModalElements()) { + + Optional estCfg = configs.getModalElement(cfg.mode); + + estCfg.ifPresent(drtEstimatorConfigGroup -> install(new ModeModule(cfg, drtEstimatorConfigGroup))); + } + } + + static final class ModeModule extends AbstractDvrpModeModule { + + private final DrtConfigGroup cfg; + private final DrtEstimatorConfigGroup group; + + public ModeModule(DrtConfigGroup cfg, DrtEstimatorConfigGroup group) { + super(group.mode); + this.cfg = cfg; + this.group = group; + } + + @Override + public void install() { + + // try with default injections and overwrite + if (group.estimator == DrtEstimatorConfigGroup.EstimatorType.BASIC) { + bindModal(DrtEstimator.class).toProvider(modalProvider( + getter -> new BasicDrtEstimator(getter.getModal(DrtEventSequenceCollector.class), group, cfg) + )).in(Singleton.class); + } + + // DRT Estimators will be available as Map + MapBinder.newMapBinder(this.binder(), DvrpMode.class, DrtEstimator.class) + .addBinding(DvrpModes.mode(getMode())) + .to(modalKey(DrtEstimator.class)); + + addControlerListenerBinding().to(modalKey(DrtEstimator.class)); + + bindModal(DrtEstimatorConfigGroup.class).toInstance(group); + + // Needs to run before estimators + bindModal(DrtEstimateAnalyzer.class) + .toProvider( + modalProvider(getter -> new DrtEstimateAnalyzer(getter.getModal(DrtEstimator.class), getter.getModal(DrtEventSequenceCollector.class), group)) + ) + .in(Singleton.class); + + addControlerListenerBinding().to(modalKey(DrtEstimateAnalyzer.class)); + + } + + } +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/run/MultiModeDrtEstimatorConfigGroup.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/run/MultiModeDrtEstimatorConfigGroup.java new file mode 100644 index 00000000000..b998bf78648 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/estimator/run/MultiModeDrtEstimatorConfigGroup.java @@ -0,0 +1,103 @@ +/* + * *********************************************************************** * + * project: org.matsim.* + * *********************************************************************** * + * * + * copyright : (C) 2018 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** * + */ + +package org.matsim.contrib.drt.extension.estimator.run; + +import java.util.Collection; +import java.util.Optional; +import java.util.function.Supplier; + +import org.matsim.contrib.dvrp.run.MultiModal; +import org.matsim.contrib.dvrp.run.MultiModals; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.config.ReflectiveConfigGroup; + +import com.google.common.base.Verify; + +/** + * @author Michal Maciejewski (michalm) + */ +public final class MultiModeDrtEstimatorConfigGroup extends ReflectiveConfigGroup implements MultiModal { + public static final String GROUP_NAME = "drtEstimators"; + + /** + * @param config + * @return MultiModeDrtConfigGroup if exists. Otherwise fails + */ + public static MultiModeDrtEstimatorConfigGroup get(Config config) { + return (MultiModeDrtEstimatorConfigGroup)config.getModule(GROUP_NAME); + } + + private final Supplier drtConfigSupplier; + + public MultiModeDrtEstimatorConfigGroup() { + this(DrtEstimatorConfigGroup::new); + } + + public MultiModeDrtEstimatorConfigGroup(Supplier drtConfigSupplier) { + super(GROUP_NAME); + this.drtConfigSupplier = drtConfigSupplier; + } + + @Override + protected void checkConsistency(Config config) { + super.checkConsistency(config); + Verify.verify(config.getModule(DrtEstimatorConfigGroup.GROUP_NAME) == null, + "In the multi-mode DRT setup, DrtEstimatorConfigGroup must not be defined at the config top level"); + MultiModals.requireAllModesUnique(this); + } + + @Override + public ConfigGroup createParameterSet(String type) { + if (type.equals(DrtEstimatorConfigGroup.GROUP_NAME)) { + return drtConfigSupplier.get(); + } else { + throw new IllegalArgumentException("Unsupported parameter set type: " + type); + } + } + + @Override + public void addParameterSet(ConfigGroup set) { + if (set instanceof DrtEstimatorConfigGroup) { + super.addParameterSet(set); + } else { + throw new IllegalArgumentException("Unsupported parameter set class: " + set); + } + } + + public void addParameterSet(DrtEstimatorConfigGroup set) { + addParameterSet((ConfigGroup) set); + } + + @Override + @SuppressWarnings("unchecked") + public Collection getModalElements() { + return (Collection)getParameterSets(DrtEstimatorConfigGroup.GROUP_NAME); + } + + /** + * Find estimator config for specific mode. + */ + public Optional getModalElement(String mode) { + return getModalElements().stream().filter(m -> m.getMode().equals(mode)).findFirst(); + } + +} diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/DrtTestScenario.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/DrtTestScenario.java index db01301303c..7131c33a368 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/DrtTestScenario.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/DrtTestScenario.java @@ -24,12 +24,14 @@ import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; import org.matsim.simwrapper.SimWrapperModule; +import org.matsim.modechoice.InformedModeChoiceConfigGroup; import org.matsim.testcases.MatsimTestUtils; import org.matsim.vehicles.VehicleType; import javax.annotation.Nullable; import java.net.URL; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.function.Consumer; @@ -82,6 +84,8 @@ protected Config prepareConfig(Config config) { config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams("freight_start").setTypicalDuration(60 * 15)); config.scoring().addActivityParams(new ScoringConfigGroup.ActivityParams("freight_end").setTypicalDuration(60 * 15)); + InformedModeChoiceConfigGroup imc = ConfigUtils.addOrGetModule(config, InformedModeChoiceConfigGroup.class); + imc.setModes(Set.of("drt", "av", "car", "pt", "bike", "walk")); MultiModeDrtConfigGroup multiModeDrtConfig = ConfigUtils.addOrGetModule(config, MultiModeDrtConfigGroup.class); ConfigUtils.addOrGetModule(config, DvrpConfigGroup.class); diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimatorTest.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimatorTest.java new file mode 100644 index 00000000000..8d61ef68123 --- /dev/null +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/estimator/MultiModalDrtLegEstimatorTest.java @@ -0,0 +1,90 @@ +package org.matsim.contrib.drt.extension.estimator; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.matsim.application.MATSimApplication; +import org.matsim.contrib.drt.extension.DrtTestScenario; +import org.matsim.contrib.drt.extension.estimator.run.DrtEstimatorConfigGroup; +import org.matsim.contrib.drt.extension.estimator.run.DrtEstimatorModule; +import org.matsim.contrib.drt.extension.estimator.run.MultiModeDrtEstimatorConfigGroup; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.ReplanningConfigGroup; +import org.matsim.core.controler.Controler; +import org.matsim.modechoice.InformedModeChoiceModule; +import org.matsim.modechoice.ModeOptions; +import org.matsim.modechoice.estimators.DefaultLegScoreEstimator; +import org.matsim.modechoice.estimators.FixedCostsEstimator; +import org.matsim.testcases.MatsimTestUtils; + +import java.io.File; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MultiModalDrtLegEstimatorTest { + + @Rule + public MatsimTestUtils utils = new MatsimTestUtils(); + + private Controler controler; + + @Before + public void setUp() throws Exception { + + Config config = DrtTestScenario.loadConfig(utils); + + config.controller().setLastIteration(3); + + controler = MATSimApplication.prepare(new DrtTestScenario(MultiModalDrtLegEstimatorTest::prepare, MultiModalDrtLegEstimatorTest::prepare), config); + } + + private static void prepare(Controler controler) { + InformedModeChoiceModule.Builder builder = InformedModeChoiceModule.newBuilder() + .withFixedCosts(FixedCostsEstimator.DailyConstant.class, "car") + .withLegEstimator(DefaultLegScoreEstimator.class, ModeOptions.AlwaysAvailable.class, "bike", "walk", "pt") + .withLegEstimator(DefaultLegScoreEstimator.class, ModeOptions.ConsiderYesAndNo.class, "car") + .withLegEstimator(MultiModalDrtLegEstimator.class, ModeOptions.AlwaysAvailable.class, "drt", "av"); + + controler.addOverridingModule(builder.build()); + controler.addOverridingModule(new DrtEstimatorModule()); + } + + private static void prepare(Config config) { + + MultiModeDrtEstimatorConfigGroup estimators = ConfigUtils.addOrGetModule(config, MultiModeDrtEstimatorConfigGroup.class); + + estimators.addParameterSet(new DrtEstimatorConfigGroup("drt")); + estimators.addParameterSet(new DrtEstimatorConfigGroup("av")); + + // Set subtour mode selection as strategy + List strategies = config.replanning().getStrategySettings().stream() + .filter(s -> !s.getStrategyName().toLowerCase().contains("mode") + ).collect(Collectors.toList()); + + strategies.add(new ReplanningConfigGroup.StrategySettings() + .setStrategyName(InformedModeChoiceModule.SELECT_SUBTOUR_MODE_STRATEGY) + .setSubpopulation("person") + .setWeight(0.2)); + + config.replanning().clearStrategySettings(); + strategies.forEach(s -> config.replanning().addStrategySettings(s)); + + } + + @Test + public void run() { + + String out = utils.getOutputDirectory(); + + controler.run(); + + assertThat(new File(out, "kelheim-mini-drt.drt_estimates_drt.csv")) + .exists() + .isNotEmpty(); + + + } +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/speedup/DrtTeleportedRouteCalculator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/speedup/DrtTeleportedRouteCalculator.java index 7935a2403e8..eca53f0c0d7 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/speedup/DrtTeleportedRouteCalculator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/speedup/DrtTeleportedRouteCalculator.java @@ -40,6 +40,12 @@ public class DrtTeleportedRouteCalculator implements TeleportedRouteCalculator { this.averageInVehicleBeelineSpeed = averageInVehicleBeelineSpeed; } + // TODO: from discussion from michal and rakow + // speedup is currently using very simple and not exchangeable estimators + // it could be possible to integrate the drt estimators used by the informed mode-choice + // this router should probably not use the beeline distance but the direct travel route + // speed-up would still be significant (oct'23) + @Override public Route calculateRoute(PassengerRequest request) { Link startLink = request.getFromLink(); diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/VehicleChargingHandler.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/VehicleChargingHandler.java index 81f6682c3ff..4a2655a5ccf 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/VehicleChargingHandler.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/VehicleChargingHandler.java @@ -42,7 +42,7 @@ import org.matsim.contrib.ev.fleet.ElectricVehicle; import org.matsim.contrib.ev.infrastructure.Charger; import org.matsim.contrib.ev.infrastructure.ChargingInfrastructure; -import org.matsim.contrib.ev.infrastructure.ChargingInfrastructures; +import org.matsim.contrib.ev.infrastructure.ChargingInfrastructureUtils; import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.events.MobsimScopeEventHandler; import org.matsim.vehicles.Vehicle; @@ -73,7 +73,7 @@ public class VehicleChargingHandler VehicleChargingHandler(ChargingInfrastructure chargingInfrastructure, ElectricFleet electricFleet) { this.chargingInfrastructure = chargingInfrastructure; this.electricFleet = electricFleet; - chargersAtLinks = ChargingInfrastructures.getChargersAtLinks(chargingInfrastructure); + chargersAtLinks = ChargingInfrastructureUtils.getChargersAtLinks(chargingInfrastructure ); } /** diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DischargingModule.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DischargingModule.java index c36f95635a9..96078d1eab1 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DischargingModule.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DischargingModule.java @@ -29,7 +29,7 @@ /** * @author Michal Maciejewski (michalm) */ -public class DischargingModule extends AbstractModule { +public final class DischargingModule extends AbstractModule { @Override public void install() { bind(DriveEnergyConsumption.Factory.class).toInstance(ev -> new OhdeSlaskiDriveEnergyConsumption()); diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DriveDischargingHandler.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DriveDischargingHandler.java index eae4a115384..ca8508a0e74 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DriveDischargingHandler.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DriveDischargingHandler.java @@ -44,7 +44,7 @@ * calculating the drive-related energy consumption. However, the time spent on the first link is used by the time-based * idle discharge process (see {@link IdleDischargingHandler}). */ -public class DriveDischargingHandler +public final class DriveDischargingHandler implements LinkLeaveEventHandler, VehicleEntersTrafficEventHandler, VehicleLeavesTrafficEventHandler, MobsimScopeEventHandler { private static class EvDrive { private final Id vehicleId; diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DrivingEnergyConsumptionEvent.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DrivingEnergyConsumptionEvent.java index f00009b3e7a..3289446a72e 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DrivingEnergyConsumptionEvent.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/DrivingEnergyConsumptionEvent.java @@ -27,7 +27,7 @@ /** * @author Michal Maciejewski (michalm) */ -public class DrivingEnergyConsumptionEvent extends AbstractEnergyConsumptionEvent { +public final class DrivingEnergyConsumptionEvent extends AbstractEnergyConsumptionEvent { public static final String EVENT_TYPE = "drivingEnergyConsumption"; public DrivingEnergyConsumptionEvent(double time, Id vehicleId, Id linkId, double energy, double endCharge) { diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/IdleDischargingHandler.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/IdleDischargingHandler.java index da6fab88948..20a90c08e13 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/IdleDischargingHandler.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/IdleDischargingHandler.java @@ -45,7 +45,7 @@ * VehicleProvider is responsible to decide if AUX discharging applies to a given vehicle based on information from * ActivityStartEvent. */ -public class IdleDischargingHandler +public final class IdleDischargingHandler implements MobsimAfterSimStepListener, ActivityStartEventHandler, ActivityEndEventHandler, MobsimScopeEventHandler { public interface VehicleProvider { /** diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/IdlingEnergyConsumptionEvent.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/IdlingEnergyConsumptionEvent.java index d992dc363f5..fcb625ad7b6 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/IdlingEnergyConsumptionEvent.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/IdlingEnergyConsumptionEvent.java @@ -27,7 +27,7 @@ /** * @author Michal Maciejewski (michalm) */ -public class IdlingEnergyConsumptionEvent extends AbstractEnergyConsumptionEvent { +public final class IdlingEnergyConsumptionEvent extends AbstractEnergyConsumptionEvent { public static final String EVENT_TYPE = "idlingEnergyConsumption"; public IdlingEnergyConsumptionEvent(double time, Id vehicleId, Id linkId, double energy, double endCharge) { diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/LTHDriveEnergyConsumption.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/LTHDriveEnergyConsumption.java index afc8d17d93a..ea20f84a484 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/LTHDriveEnergyConsumption.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/LTHDriveEnergyConsumption.java @@ -32,7 +32,7 @@ import com.google.common.primitives.Doubles; -public class LTHDriveEnergyConsumption implements DriveEnergyConsumption { +public final class LTHDriveEnergyConsumption implements DriveEnergyConsumption { private final PiecewiseBicubicSplineInterpolatingFunction function; diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/MissingEnergyEvent.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/MissingEnergyEvent.java index a85c043522d..ef120c09fa9 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/MissingEnergyEvent.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/MissingEnergyEvent.java @@ -26,7 +26,7 @@ import org.matsim.api.core.v01.network.Link; import org.matsim.vehicles.Vehicle; -public class MissingEnergyEvent extends Event { +public final class MissingEnergyEvent extends Event { public static final String EVENT_TYPE = "missing_energy"; public static final String ATTRIBUTE_VEHICLE = "vehicle"; public static final String ATTRIBUTE_ENERGY = "energy"; diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/OhdeSlaskiAuxEnergyConsumption.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/OhdeSlaskiAuxEnergyConsumption.java index 39d93db41c0..b344474bf9d 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/OhdeSlaskiAuxEnergyConsumption.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/OhdeSlaskiAuxEnergyConsumption.java @@ -27,7 +27,7 @@ import com.google.common.base.Preconditions; import com.google.inject.Inject; -public class OhdeSlaskiAuxEnergyConsumption implements AuxEnergyConsumption { +public final class OhdeSlaskiAuxEnergyConsumption implements AuxEnergyConsumption { private static final double a = 1.3;// [W] private static final double b = -63.4;// [W] private static final double c = 1748.1;// [W] @@ -46,7 +46,7 @@ private static double calcPower(double temp) { private final TemperatureService temperatureService; - public OhdeSlaskiAuxEnergyConsumption(TemperatureService temperatureService) { + OhdeSlaskiAuxEnergyConsumption(TemperatureService temperatureService) { this.temperatureService = temperatureService; } @@ -59,7 +59,7 @@ public static class Factory implements AuxEnergyConsumption.Factory { private final TemperatureService temperatureService; @Inject - public Factory(TemperatureService temperatureService) { + Factory(TemperatureService temperatureService) { this.temperatureService = temperatureService; } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/OhdeSlaskiDriveEnergyConsumption.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/OhdeSlaskiDriveEnergyConsumption.java index dafad6d76d1..44b62145719 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/OhdeSlaskiDriveEnergyConsumption.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/OhdeSlaskiDriveEnergyConsumption.java @@ -30,7 +30,7 @@ * https://www.researchgate.net/profile/Michal-Maciejewski-3/publication/312393169_Statistical_analysis_of_real-world_urban_driving_cycles_for_modelling_energy_consumption_of_electric_vehicles/links/59b7a17faca2722453a5fc7f/Statistical-analysis-of-real-world-urban-driving-cycles-for-modelling-energy-consumption-of-electric-vehicles.pdf * TODO Add (dis-)charging efficiency relative to SOC, temperature, etc... */ -public class OhdeSlaskiDriveEnergyConsumption implements DriveEnergyConsumption { +public final class OhdeSlaskiDriveEnergyConsumption implements DriveEnergyConsumption { private static final double g = 9.81; // g [m/s^2] private static final double m = 1525; // vehicle mass [kg] private static final double m_s = m + 100; // vehicle mass + extra mass [kg] diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/VehicleTypeSpecificDriveEnergyConsumptionFactory.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/VehicleTypeSpecificDriveEnergyConsumptionFactory.java index b905a6f881e..4310d786b80 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/VehicleTypeSpecificDriveEnergyConsumptionFactory.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/discharging/VehicleTypeSpecificDriveEnergyConsumptionFactory.java @@ -29,7 +29,7 @@ import org.matsim.contrib.ev.fleet.ElectricVehicle; import org.matsim.vehicles.VehicleType; -public class VehicleTypeSpecificDriveEnergyConsumptionFactory implements DriveEnergyConsumption.Factory { +public final class VehicleTypeSpecificDriveEnergyConsumptionFactory implements DriveEnergyConsumption.Factory { private final Map, DriveEnergyConsumption.Factory> consumptionMap = new HashMap<>(); diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/example/RunEvExample.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/example/RunEvExample.java index 406f0e647dc..e4980391db6 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/example/RunEvExample.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/example/RunEvExample.java @@ -71,8 +71,11 @@ public void run( String[] args ) { install( new EvModule() ); addRoutingModuleBinding( TransportMode.car ).toProvider(new EvNetworkRoutingProvider(TransportMode.car) ); - // a router that inserts charging activities when the battery is run empty. there may be some other way to insert - // charging activities, based on the situation. kai, dec'22 + // a router that inserts charging activities INTO THE ROUTE when the battery is run empty. This assumes that a full + // charge at the start of the route is not sufficient to drive the route. There are other settings where the + // situation is different, e.g. urban, where there may be a CHAIN of activities, and charging in general is done in + // parallel with some of these activities. That second situation is adressed by some "ev" code in the vsp contrib. + // kai, dec'22 } } ); diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/example/RunEvExampleWithLTHConsumptionModel.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/example/RunEvExampleWithLTHConsumptionModel.java index 15ed10c0627..024bc2e4c54 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/example/RunEvExampleWithLTHConsumptionModel.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/example/RunEvExampleWithLTHConsumptionModel.java @@ -89,7 +89,7 @@ public void run( String[] args ) { VehicleTypeSpecificDriveEnergyConsumptionFactory driveEnergyConsumptionFactory = new VehicleTypeSpecificDriveEnergyConsumptionFactory(); var vehicleType = Id.create( "EV_65.0kWh", VehicleType.class ); driveEnergyConsumptionFactory.addEnergyConsumptionModelFactory( vehicleType, - new LTHConsumptionModelReader( vehicleType ).readURL( ConfigGroup.getInputFileURL( config.getContext(), "MidCarMap.csv" ) ) ); + new LTHConsumptionModelReader().readURL( ConfigGroup.getInputFileURL( config.getContext(), "MidCarMap.csv" ) ) ); controler.addOverridingModule( new EvModule() ); controler.addOverridingModule( new AbstractModule(){ @@ -106,6 +106,7 @@ public void install(){ } ); } + controler.run(); } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/example/RunEvExampleWithOwnConsumptionModel.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/example/RunEvExampleWithOwnConsumptionModel.java new file mode 100644 index 00000000000..eacaba778ad --- /dev/null +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/example/RunEvExampleWithOwnConsumptionModel.java @@ -0,0 +1,137 @@ +/* *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2016 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +package org.matsim.contrib.ev.example; +/* + * created by jbischoff, 19.03.2019 + */ + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.ev.EvConfigGroup; +import org.matsim.contrib.ev.EvModule; +import org.matsim.contrib.ev.discharging.AuxEnergyConsumption; +import org.matsim.contrib.ev.discharging.DriveEnergyConsumption; +import org.matsim.contrib.ev.discharging.LTHDriveEnergyConsumption; +import org.matsim.contrib.ev.fleet.ElectricVehicle; +import org.matsim.contrib.ev.infrastructure.LTHConsumptionModelReader; +import org.matsim.contrib.ev.routing.EvNetworkRoutingProvider; +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.Controler; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.scenario.ScenarioUtils; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; + +/** + * Runs a sample EV run using a vehicle consumption model designed at LTH in Lund which takes the speed and the slope of a link into account. + * Link slopes may be added using a double array on the network. + * The consumption maps are based on Domingues, Gabriel. / Modeling, Optimization and Analysis of Electromobility Systems. Lund : Department of Biomedical Engineering, Lund university, 2018. 169 p., PhD thesis + */ +public class RunEvExampleWithOwnConsumptionModel{ + static final String DEFAULT_CONFIG_FILE = "test/input/org/matsim/contrib/ev/example/RunEvExample/config.xml"; + private static final Logger log = LogManager.getLogger( RunEvExampleWithOwnConsumptionModel.class ); + + public static void main(String[] args) throws IOException { + if (args.length > 0) { + log.info("Starting simulation run with the following arguments:"); + log.info("args=" + Arrays.toString( args ) ); + } else { + File localConfigFile = new File(DEFAULT_CONFIG_FILE); + if (localConfigFile.exists()) { + log.info("Starting simulation run with the local example config file"); + args = new String[]{ DEFAULT_CONFIG_FILE }; + } else { + log.info("Starting simulation run with the example config file from GitHub repository"); + args = new String[]{"https://raw.githubusercontent.com/matsim-org/matsim/master/contribs/ev/" + + DEFAULT_CONFIG_FILE }; + } + } + new RunEvExampleWithOwnConsumptionModel().run(args ); + } + + public void run( String[] args ) { + Config config = ConfigUtils.loadConfig(args, new EvConfigGroup()); + config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + + // === + + Scenario scenario = ScenarioUtils.loadScenario(config); + + // === + + Controler controler = new Controler(scenario); + { + DriveEnergyConsumption.Factory driveEnergyConsumptionFactory = new DriveEnergyConsumption.Factory(){ + @Override public DriveEnergyConsumption create( ElectricVehicle electricVehicle ){ + DriveEnergyConsumption.Factory factory = new LTHConsumptionModelReader().readURL( ConfigGroup.getInputFileURL( config.getContext(), "MidCarMap.csv" ) ); + DriveEnergyConsumption delegate = factory.create( electricVehicle ); + + DriveEnergyConsumption consumption = new DriveEnergyConsumption(){ + @Override public double calcEnergyConsumption( Link link, double travelTime, double linkEnterTime ){ + + // discharge because the link must be driven: + double delta = delegate.calcEnergyConsumption( link, travelTime, linkEnterTime ); + + double desiredSocAtEndOfLink = (double) electricVehicle.getVehicleSpecification().getMatsimVehicle().getAttributes().getAttribute( "whatever" ); + + return electricVehicle.getBattery().getSoc() - desiredSocAtEndOfLink; + // * above will often be negative; this is the purpose: discharging is negative i.e. we are + // charging on the link. ((This is why I am in general against hiding the sign in the method + // name. kai)) + + // * above is in SOC space, needs to be translated into kWh space + + // * need to make sure that the above charging is physically possible + + // * need to make sure that we are not discharging beyond what is needed to drive the link + + } + }; + return consumption; + } + }; + + controler.addOverridingModule( new EvModule() ); + controler.addOverridingModule( new AbstractModule(){ + @Override + public void install(){ + bind( DriveEnergyConsumption.Factory.class ).toInstance( driveEnergyConsumptionFactory ); + bind( AuxEnergyConsumption.Factory.class ).toInstance( + electricVehicle -> ( beginTime, duration, linkId ) -> 0 ); //a dummy factory, as aux consumption is part of the drive consumption in the model + + addRoutingModuleBinding( TransportMode.car ).toProvider( new EvNetworkRoutingProvider( TransportMode.car ) ); + // a router that inserts charging activities when the battery is run empty. there may be some other way to insert + // charging activities, based on the situation. kai, dec'22 + } + } ); + } + + + controler.run(); + } +} diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/BatteryImpl.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/BatteryDefaultImpl.java similarity index 94% rename from contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/BatteryImpl.java rename to contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/BatteryDefaultImpl.java index b3be0ab8a02..a9629018dfc 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/BatteryImpl.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/BatteryDefaultImpl.java @@ -23,11 +23,11 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; -public class BatteryImpl implements Battery { +final class BatteryDefaultImpl implements Battery { private final double capacity; private double charge; - public BatteryImpl(double capacity, double charge) { + BatteryDefaultImpl( double capacity, double charge ) { this.capacity = capacity; this.charge = charge; } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ConvertInitialChargeToInitialSoc.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ConvertInitialChargeToInitialSoc.java deleted file mode 100644 index 2f1475f964e..00000000000 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ConvertInitialChargeToInitialSoc.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * *********************************************************************** * - * project: org.matsim.* - * *********************************************************************** * - * * - * copyright : (C) 2022 by the members listed in the COPYING, * - * LICENSE and WARRANTY file. * - * email : info at matsim dot org * - * * - * *********************************************************************** * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * See also COPYING, LICENSE and WARRANTY file * - * * - * *********************************************************************** * - */ - -package org.matsim.contrib.ev.fleet; - -import static org.matsim.contrib.ev.fleet.ElectricVehicleSpecificationImpl.INITIAL_SOC; - -import org.matsim.vehicles.MatsimVehicleReader; -import org.matsim.vehicles.MatsimVehicleWriter; -import org.matsim.vehicles.VehicleUtils; - -/** - * @author Michal Maciejewski (michalm) - */ -public class ConvertInitialChargeToInitialSoc { - private static final String INITIAL_ENERGY_kWh = "initialEnergyInKWh"; - - public static void run(String file) { - var vehicles = VehicleUtils.createVehiclesContainer(); - var reader = new MatsimVehicleReader(vehicles); - reader.readFile(file); - - for (var v : vehicles.getVehicles().values()) { - double battery_kWh = VehicleUtils.getEnergyCapacity(v.getType().getEngineInformation()); - double initial_kWh = (double)v.getAttributes().getAttribute(INITIAL_ENERGY_kWh); - double initial_soc = initial_kWh / battery_kWh; - v.getAttributes().removeAttribute(INITIAL_ENERGY_kWh); - v.getAttributes().putAttribute(INITIAL_SOC, initial_soc); - } - - var writer = new MatsimVehicleWriter(vehicles); - writer.writeFile(file); - } -} diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetModule.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetModule.java index fc6493ae3b8..179a6ec9116 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetModule.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetModule.java @@ -37,7 +37,7 @@ /** * @author Michal Maciejewski (michalm) */ -public class ElectricFleetModule extends AbstractModule { +public final class ElectricFleetModule extends AbstractModule { @Inject private EvConfigGroup evCfg; @@ -46,9 +46,9 @@ public void install() { bind(ElectricFleetSpecification.class).toProvider(new Provider<>() { @Inject private Vehicles vehicles; @Override public ElectricFleetSpecification get() { - ElectricFleetSpecification fleetSpecification = new ElectricFleetSpecificationImpl(); - ElectricVehicleSpecificationImpl.createAndAddVehicleSpecificationsFromMatsimVehicles(fleetSpecification, - vehicles.getVehicles().values()); + ElectricFleetSpecification fleetSpecification = new ElectricFleetSpecificationDefaultImpl(); + ElectricFleetUtils.createAndAddVehicleSpecificationsFromMatsimVehicles(fleetSpecification, + vehicles.getVehicles().values() ); return fleetSpecification; } }).asEagerSingleton(); @@ -64,8 +64,8 @@ protected void configureQSim() { @Override public ElectricFleet get() { - return ElectricFleets.createDefaultFleet(fleetSpecification, driveConsumptionFactory, auxConsumptionFactory, - chargingPowerFactory); + return ElectricFleetUtils.createDefaultFleet(fleetSpecification, driveConsumptionFactory, auxConsumptionFactory, + chargingPowerFactory ); } }).asEagerSingleton(); @@ -77,7 +77,7 @@ public ElectricFleet get() { for (var oldSpec : electricFleetSpecification.getVehicleSpecifications().values()) { var matsimVehicle = oldSpec.getMatsimVehicle(); double socAtEndOfCurrentIteration = electricFleet.getElectricVehicles().get(oldSpec.getId()).getBattery().getSoc(); - ElectricVehicleSpecifications.setInitialSoc(matsimVehicle, socAtEndOfCurrentIteration); + ElectricFleetUtils.setInitialSoc(matsimVehicle, socAtEndOfCurrentIteration ); } } }); diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetSpecificationImpl.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetSpecificationDefaultImpl.java similarity index 96% rename from contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetSpecificationImpl.java rename to contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetSpecificationDefaultImpl.java index 14a70682741..b24583feb13 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetSpecificationImpl.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetSpecificationDefaultImpl.java @@ -30,7 +30,7 @@ /** * @author Michal Maciejewski (michalm) */ -public final class ElectricFleetSpecificationImpl implements ElectricFleetSpecification { +final class ElectricFleetSpecificationDefaultImpl implements ElectricFleetSpecification { private final Map, ElectricVehicleSpecification> specifications = new LinkedHashMap<>(); @Override diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetUtils.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetUtils.java new file mode 100644 index 00000000000..0e92b52759c --- /dev/null +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleetUtils.java @@ -0,0 +1,90 @@ +/* + * *********************************************************************** * + * project: org.matsim.* + * *********************************************************************** * + * * + * copyright : (C) 2022 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** * + */ + +package org.matsim.contrib.ev.fleet; + +import java.util.Collection; +import java.util.Objects; + +import com.google.common.collect.ImmutableMap; +import org.matsim.api.core.v01.Id; +import org.matsim.contrib.ev.charging.ChargingPower; +import org.matsim.contrib.ev.discharging.AuxEnergyConsumption; +import org.matsim.contrib.ev.discharging.DriveEnergyConsumption; +import org.matsim.vehicles.*; + +public final class ElectricFleetUtils { + public static final String EV_ENGINE_HBEFA_TECHNOLOGY = "electricity"; + public static final String INITIAL_SOC = "initialSoc";// in [0, 1] + public static final String CHARGER_TYPES = "chargerTypes"; + private static final String INITIAL_ENERGY_kWh = "initialEnergyInKWh"; + private ElectricFleetUtils(){} // do not instantiate + public static void setInitialSoc(Vehicle vehicle, double initialSoc) { + vehicle.getAttributes().putAttribute( INITIAL_SOC, initialSoc ); + } + + public static void setChargerTypes(EngineInformation engineInformation, Collection chargerTypes) { + engineInformation.getAttributes().putAttribute( CHARGER_TYPES, chargerTypes ); + } + public static void run(String file) { + var vehicles = VehicleUtils.createVehiclesContainer(); + var reader = new MatsimVehicleReader(vehicles); + reader.readFile(file); + + for (var v : vehicles.getVehicles().values()) { + double battery_kWh = VehicleUtils.getEnergyCapacity(v.getType().getEngineInformation()); + double initial_kWh = (double)v.getAttributes().getAttribute(INITIAL_ENERGY_kWh); + double initial_soc = initial_kWh / battery_kWh; + v.getAttributes().removeAttribute(INITIAL_ENERGY_kWh); + v.getAttributes().putAttribute(INITIAL_SOC, initial_soc); + } + + var writer = new MatsimVehicleWriter(vehicles); + writer.writeFile(file); + } + public static ElectricVehicle create( ElectricVehicleSpecification vehicleSpecification, + DriveEnergyConsumption.Factory driveFactory, AuxEnergyConsumption.Factory auxFactory, + ChargingPower.Factory chargingFactory ) { + ElectricVehicleDefaultImpl ev = new ElectricVehicleDefaultImpl(vehicleSpecification); + ev.driveEnergyConsumption = Objects.requireNonNull(driveFactory.create(ev ) ); + ev.auxEnergyConsumption = Objects.requireNonNull(auxFactory.create(ev)); + ev.chargingPower = Objects.requireNonNull(chargingFactory.create(ev)); + return ev; + } + public static void createAndAddVehicleSpecificationsFromMatsimVehicles(ElectricFleetSpecification fleetSpecification, Collection vehicles) { + vehicles.stream() + .filter(vehicle -> EV_ENGINE_HBEFA_TECHNOLOGY.equals(VehicleUtils.getHbefaTechnology(vehicle.getType().getEngineInformation()))) + .map( ElectricVehicleSpecificationDefaultImpl::new ) + .forEach(fleetSpecification::addVehicleSpecification); + } + public static ElectricVehicleSpecification createElectricVehicleSpecificationDefaultImpl( Vehicle matsimVehicle ){ + return new ElectricVehicleSpecificationDefaultImpl( matsimVehicle ); + } + public static ElectricFleet createDefaultFleet(ElectricFleetSpecification fleetSpecification, + DriveEnergyConsumption.Factory driveConsumptionFactory, AuxEnergyConsumption.Factory auxConsumptionFactory, + ChargingPower.Factory chargingFactory) { + ImmutableMap, ElectricVehicle> vehicles = fleetSpecification.getVehicleSpecifications() + .values() + .stream() + .map(s -> create(s, driveConsumptionFactory, auxConsumptionFactory, chargingFactory )) + .collect(ImmutableMap.toImmutableMap(ElectricVehicle::getId, v -> v)); + return () -> vehicles; + } +} diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleets.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleets.java deleted file mode 100644 index fbe29db0ab3..00000000000 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricFleets.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * *********************************************************************** * - * project: org.matsim.* - * *********************************************************************** * - * * - * copyright : (C) 2019 by the members listed in the COPYING, * - * LICENSE and WARRANTY file. * - * email : info at matsim dot org * - * * - * *********************************************************************** * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * See also COPYING, LICENSE and WARRANTY file * - * * - * *********************************************************************** * - */ - -package org.matsim.contrib.ev.fleet; - -import org.matsim.api.core.v01.Id; -import org.matsim.contrib.ev.charging.ChargingPower; -import org.matsim.contrib.ev.discharging.AuxEnergyConsumption; -import org.matsim.contrib.ev.discharging.DriveEnergyConsumption; -import org.matsim.vehicles.Vehicle; - -import com.google.common.collect.ImmutableMap; - -public class ElectricFleets { - public static ElectricFleet createDefaultFleet(ElectricFleetSpecification fleetSpecification, - DriveEnergyConsumption.Factory driveConsumptionFactory, AuxEnergyConsumption.Factory auxConsumptionFactory, - ChargingPower.Factory chargingFactory) { - ImmutableMap, ElectricVehicle> vehicles = fleetSpecification.getVehicleSpecifications() - .values() - .stream() - .map(s -> ElectricVehicleImpl.create(s, driveConsumptionFactory, auxConsumptionFactory, - chargingFactory)) - .collect(ImmutableMap.toImmutableMap(ElectricVehicle::getId, v -> v)); - return () -> vehicles; - } -} diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleImpl.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleDefaultImpl.java similarity index 74% rename from contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleImpl.java rename to contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleDefaultImpl.java index 91125b6500d..c4da3c65565 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleImpl.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleDefaultImpl.java @@ -20,8 +20,6 @@ package org.matsim.contrib.ev.fleet; -import java.util.Objects; - import org.matsim.api.core.v01.Id; import org.matsim.contrib.ev.charging.ChargingPower; import org.matsim.contrib.ev.discharging.AuxEnergyConsumption; @@ -31,27 +29,18 @@ import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableList; -public class ElectricVehicleImpl implements ElectricVehicle { - public static ElectricVehicle create(ElectricVehicleSpecification vehicleSpecification, - DriveEnergyConsumption.Factory driveFactory, AuxEnergyConsumption.Factory auxFactory, - ChargingPower.Factory chargingFactory) { - ElectricVehicleImpl ev = new ElectricVehicleImpl(vehicleSpecification); - ev.driveEnergyConsumption = Objects.requireNonNull(driveFactory.create(ev)); - ev.auxEnergyConsumption = Objects.requireNonNull(auxFactory.create(ev)); - ev.chargingPower = Objects.requireNonNull(chargingFactory.create(ev)); - return ev; - } +final class ElectricVehicleDefaultImpl implements ElectricVehicle { private final ElectricVehicleSpecification vehicleSpecification; private final Battery battery; - private DriveEnergyConsumption driveEnergyConsumption; - private AuxEnergyConsumption auxEnergyConsumption; - private ChargingPower chargingPower; + DriveEnergyConsumption driveEnergyConsumption; + AuxEnergyConsumption auxEnergyConsumption; + ChargingPower chargingPower; - private ElectricVehicleImpl(ElectricVehicleSpecification vehicleSpecification) { + ElectricVehicleDefaultImpl( ElectricVehicleSpecification vehicleSpecification ) { this.vehicleSpecification = vehicleSpecification; - battery = new BatteryImpl(vehicleSpecification.getBatteryCapacity(), vehicleSpecification.getInitialCharge()); + battery = new BatteryDefaultImpl(vehicleSpecification.getBatteryCapacity(), vehicleSpecification.getInitialCharge()); } @Override diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleSpecificationImpl.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleSpecificationDefaultImpl.java similarity index 73% rename from contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleSpecificationImpl.java rename to contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleSpecificationDefaultImpl.java index 70d4c100f77..ef18ae6cce6 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleSpecificationImpl.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleSpecificationDefaultImpl.java @@ -33,23 +33,11 @@ /** * @author Michal Maciejewski (michalm) */ -public class ElectricVehicleSpecificationImpl implements ElectricVehicleSpecification { - public static final String EV_ENGINE_HBEFA_TECHNOLOGY = "electricity"; - - public static final String INITIAL_SOC = "initialSoc";// in [0, 1] - public static final String CHARGER_TYPES = "chargerTypes"; - - public static void createAndAddVehicleSpecificationsFromMatsimVehicles(ElectricFleetSpecification fleetSpecification, - Collection vehicles) { - vehicles.stream() - .filter(vehicle -> EV_ENGINE_HBEFA_TECHNOLOGY.equals(VehicleUtils.getHbefaTechnology(vehicle.getType().getEngineInformation()))) - .map(ElectricVehicleSpecificationImpl::new) - .forEach(fleetSpecification::addVehicleSpecification); - } +final class ElectricVehicleSpecificationDefaultImpl implements ElectricVehicleSpecification { private final Vehicle matsimVehicle; - public ElectricVehicleSpecificationImpl(Vehicle matsimVehicle) { + ElectricVehicleSpecificationDefaultImpl( Vehicle matsimVehicle ) { this.matsimVehicle = matsimVehicle; //provided per vehicle type (in engine info) Preconditions.checkArgument(getInitialSoc() >= 0 && getInitialSoc() <= 1, "Invalid initialCharge or batteryCapacity of vehicle: %s", getId()); @@ -68,12 +56,12 @@ public Vehicle getMatsimVehicle() { @Override public ImmutableList getChargerTypes() { var engineInfo = matsimVehicle.getType().getEngineInformation(); - return ImmutableList.copyOf((Collection)engineInfo.getAttributes().getAttribute(CHARGER_TYPES)); + return ImmutableList.copyOf((Collection)engineInfo.getAttributes().getAttribute( ElectricFleetUtils.CHARGER_TYPES ) ); } @Override public double getInitialSoc() { - return (double)matsimVehicle.getAttributes().getAttribute(INITIAL_SOC); + return (double)matsimVehicle.getAttributes().getAttribute( ElectricFleetUtils.INITIAL_SOC ); } @Override diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerImpl.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerDefaultImpl.java similarity index 95% rename from contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerImpl.java rename to contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerDefaultImpl.java index a37cd181c9e..d2efb68578d 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerImpl.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerDefaultImpl.java @@ -29,13 +29,13 @@ import com.google.common.base.Preconditions; -public class ChargerImpl implements Charger { +class ChargerDefaultImpl implements Charger { private final ChargerSpecification specification; private final Link link; private final ChargingLogic logic; - public ChargerImpl(ChargerSpecification specification, Link link, ChargingLogic logic) { + ChargerDefaultImpl( ChargerSpecification specification, Link link, ChargingLogic logic ) { Preconditions.checkArgument(link.getId().equals(specification.getLinkId()), "link.id != specification.linkId"); this.specification = specification; this.link = link; diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerReader.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerReader.java index 27f21fe2fff..9864622b4cb 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerReader.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerReader.java @@ -28,7 +28,7 @@ import org.matsim.core.utils.io.MatsimXmlParser; import org.xml.sax.Attributes; -public class ChargerReader extends MatsimXmlParser { +public final class ChargerReader extends MatsimXmlParser { private final static String CHARGER = "charger"; private final ChargingInfrastructureSpecification chargingInfrastructure; diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerWriter.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerWriter.java index bb03bc9f063..8955b266984 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerWriter.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargerWriter.java @@ -29,7 +29,7 @@ import org.matsim.core.utils.collections.Tuple; import org.matsim.core.utils.io.MatsimXmlWriter; -public class ChargerWriter extends MatsimXmlWriter { +public final class ChargerWriter extends MatsimXmlWriter { private final Stream chargerSpecifications; public ChargerWriter(Stream chargerSpecifications) { diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureModule.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureModule.java index ea2e2526afb..f44bee53f11 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureModule.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureModule.java @@ -36,7 +36,7 @@ /** * @author Michal Maciejewski (michalm) */ -public class ChargingInfrastructureModule extends AbstractModule { +public final class ChargingInfrastructureModule extends AbstractModule { public static final String CHARGERS = "chargers"; private final Key networkKey; @@ -56,7 +56,7 @@ public void install() { bind(Network.class).annotatedWith(Names.named(CHARGERS)).to(networkKey).asEagerSingleton(); bind(ChargingInfrastructureSpecification.class).toProvider(() -> { - ChargingInfrastructureSpecification chargingInfrastructureSpecification = new ChargingInfrastructureSpecificationImpl(); + ChargingInfrastructureSpecification chargingInfrastructureSpecification = new ChargingInfrastructureSpecificationDefaultImpl(); new ChargerReader(chargingInfrastructureSpecification).parse( ConfigGroup.getInputFileURL(getConfig().getContext(), evCfg.chargersFile)); return chargingInfrastructureSpecification; @@ -76,8 +76,8 @@ protected void configureQSim() { @Override public ChargingInfrastructure get() { - return ChargingInfrastructures.createChargingInfrastructure(chargingInfrastructureSpecification, - network.getLinks()::get, chargingLogicFactory); + return ChargingInfrastructureUtils.createChargingInfrastructure(chargingInfrastructureSpecification, + network.getLinks()::get, chargingLogicFactory ); } }).asEagerSingleton(); } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureSpecificationImpl.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureSpecificationDefaultImpl.java similarity index 95% rename from contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureSpecificationImpl.java rename to contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureSpecificationDefaultImpl.java index ceeba42372f..48a27563616 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureSpecificationImpl.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureSpecificationDefaultImpl.java @@ -28,7 +28,7 @@ /** * @author Michal Maciejewski (michalm) */ -public class ChargingInfrastructureSpecificationImpl implements ChargingInfrastructureSpecification { +final class ChargingInfrastructureSpecificationDefaultImpl implements ChargingInfrastructureSpecification { private final SpecificationContainer container = new SpecificationContainer<>(); @Override diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructures.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureUtils.java similarity index 90% rename from contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructures.java rename to contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureUtils.java index b86a140fcbb..e4e7ca5c4fa 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructures.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ChargingInfrastructureUtils.java @@ -37,8 +37,10 @@ /** * @author Michal Maciejewski (michalm) */ -public class ChargingInfrastructures { - static final Logger log = LogManager.getLogger(ChargingInfrastructures.class); +public class ChargingInfrastructureUtils{ + static final Logger log = LogManager.getLogger( ChargingInfrastructureUtils.class ); + + private ChargingInfrastructureUtils(){} // do not instantiate public static ChargingInfrastructure createChargingInfrastructure( ChargingInfrastructureSpecification infrastructureSpecification, Function, Link> linkProvider, @@ -46,7 +48,7 @@ public static ChargingInfrastructure createChargingInfrastructure( var chargers = infrastructureSpecification.getChargerSpecifications() .values() .stream() - .map(s -> new ChargerImpl(s, linkProvider.apply(s.getLinkId()), chargingLogicFactory.create(s))) + .map(s -> new ChargerDefaultImpl(s, linkProvider.apply(s.getLinkId() ), chargingLogicFactory.create(s )) ) .collect(ImmutableMap.toImmutableMap(Charger::getId, c -> (Charger)c)); return () -> chargers; } @@ -72,7 +74,7 @@ public static ChargingInfrastructure createModalNetworkChargers(ChargingInfrastr var reachableLinks = network.getLinks(); var filteredChargers = infrastructure.getChargers().values().stream().map(c -> { var link = reachableLinks.get(c.getLink().getId()); - return link == null ? null : new ChargerImpl(c.getSpecification(), link, c.getLogic()); + return link == null ? null : new ChargerDefaultImpl(c.getSpecification(), link, c.getLogic()); }).filter(Objects::nonNull).collect(ImmutableMap.toImmutableMap(Charger::getId, c -> (Charger)c)); int chargerCount = infrastructure.getChargers().size(); diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ImmutableChargerSpecification.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ImmutableChargerSpecification.java index aa08f5d6b85..a3d7192b793 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ImmutableChargerSpecification.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/ImmutableChargerSpecification.java @@ -40,7 +40,7 @@ public class ImmutableChargerSpecification implements ChargerSpecification { private final double plugPower; private final int plugCount; - private ImmutableChargerSpecification(Builder builder) { + private ImmutableChargerSpecification( ChargerSpecificationBuilder builder ) { id = Objects.requireNonNull(builder.id); linkId = Objects.requireNonNull(builder.linkId); chargerType = Objects.requireNonNull(builder.chargerType); @@ -51,12 +51,12 @@ private ImmutableChargerSpecification(Builder builder) { Preconditions.checkArgument(plugCount >= 0, "Negative plugCount of charger: %s", id); } - public static Builder newBuilder() { - return new Builder(); + public static ChargerSpecificationBuilder newBuilder() { + return new ChargerSpecificationBuilder(); } - public static Builder newBuilder(ChargerSpecification copy) { - Builder builder = new Builder(); + public static ChargerSpecificationBuilder newBuilder( ChargerSpecification copy ) { + ChargerSpecificationBuilder builder = new ChargerSpecificationBuilder(); builder.id = copy.getId(); builder.linkId = copy.getLinkId(); builder.chargerType = copy.getChargerType(); @@ -101,37 +101,37 @@ public String toString() { .toString(); } - public static final class Builder { + public static final class ChargerSpecificationBuilder{ private Id id; private Id linkId; private String chargerType; private Double plugPower; private Integer plugCount; - private Builder() { + private ChargerSpecificationBuilder() { } - public Builder id(Id val) { + public ChargerSpecificationBuilder id( Id val ) { id = val; return this; } - public Builder linkId(Id val) { + public ChargerSpecificationBuilder linkId( Id val ) { linkId = val; return this; } - public Builder chargerType(String val) { + public ChargerSpecificationBuilder chargerType( String val ) { chargerType = val; return this; } - public Builder plugPower(double val) { + public ChargerSpecificationBuilder plugPower( double val ) { plugPower = val; return this; } - public Builder plugCount(int val) { + public ChargerSpecificationBuilder plugCount( int val ) { plugCount = val; return this; } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/LTHConsumptionModelReader.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/LTHConsumptionModelReader.java index 5cb4e90d129..0b8e732e85a 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/LTHConsumptionModelReader.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/infrastructure/LTHConsumptionModelReader.java @@ -28,6 +28,7 @@ import java.util.List; import org.matsim.api.core.v01.Id; +import org.matsim.contrib.ev.discharging.DriveEnergyConsumption; import org.matsim.contrib.ev.discharging.LTHDriveEnergyConsumption; import org.matsim.core.utils.io.tabularFileParser.TabularFileHandler; import org.matsim.core.utils.io.tabularFileParser.TabularFileParser; @@ -43,10 +44,10 @@ */ public class LTHConsumptionModelReader { - public LTHConsumptionModelReader(Id vehicleTypeId) { + public LTHConsumptionModelReader() { } - public LTHDriveEnergyConsumption.Factory readURL(URL fileUrl) { + public DriveEnergyConsumption.Factory readURL( URL fileUrl ) { List speeds = new ArrayList<>(); List slopes = new ArrayList<>(); TabularFileParserConfig tabularFileParserConfig = new TabularFileParserConfig(); diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/package-info.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/package-info.java index b8acc39a3f7..1ae999170d8 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/package-info.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/package-info.java @@ -17,8 +17,6 @@ * * * *********************************************************************** */ -package org.matsim.contrib.ev; - /** * All values used in this package use SI base and derived units. In particular: *
    @@ -34,3 +32,5 @@ * Consequently, energy consumption is measured in [J/m], rather than [kWh/100km] or [Wh/km], as typically done in * transport. */ +package org.matsim.contrib.ev; + diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/routing/EvNetworkRoutingModule.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/routing/EvNetworkRoutingModule.java index 6d8a0e89f61..10123db4717 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/routing/EvNetworkRoutingModule.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/routing/EvNetworkRoutingModule.java @@ -36,10 +36,7 @@ import org.matsim.contrib.ev.charging.VehicleChargingHandler; import org.matsim.contrib.ev.discharging.AuxEnergyConsumption; import org.matsim.contrib.ev.discharging.DriveEnergyConsumption; -import org.matsim.contrib.ev.fleet.ElectricFleetSpecification; -import org.matsim.contrib.ev.fleet.ElectricVehicle; -import org.matsim.contrib.ev.fleet.ElectricVehicleImpl; -import org.matsim.contrib.ev.fleet.ElectricVehicleSpecification; +import org.matsim.contrib.ev.fleet.*; import org.matsim.contrib.ev.infrastructure.ChargerSpecification; import org.matsim.contrib.ev.infrastructure.ChargingInfrastructureSpecification; import org.matsim.contrib.common.util.StraightLineKnnFinder; @@ -180,10 +177,10 @@ private Map estimateConsumption(ElectricVehicleSpecification ev, L Map consumptions = new LinkedHashMap<>(); NetworkRoute route = (NetworkRoute)basicLeg.getRoute(); List links = NetworkUtils.getLinks(network, route.getLinkIds()); - ElectricVehicle pseudoVehicle = ElectricVehicleImpl.create(ev, driveConsumptionFactory, auxConsumptionFactory, + ElectricVehicle pseudoVehicle = ElectricFleetUtils.create(ev, driveConsumptionFactory, auxConsumptionFactory, v -> charger -> { throw new UnsupportedOperationException(); - }); + } ); DriveEnergyConsumption driveEnergyConsumption = pseudoVehicle.getDriveEnergyConsumption(); AuxEnergyConsumption auxEnergyConsumption = pseudoVehicle.getAuxEnergyConsumption(); double linkEnterTime = basicLeg.getDepartureTime().seconds(); diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerOccupancyTimeProfileCollectorProvider.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerOccupancyTimeProfileCollectorProvider.java index 5c13fac0868..a11883f50f2 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerOccupancyTimeProfileCollectorProvider.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerOccupancyTimeProfileCollectorProvider.java @@ -34,12 +34,12 @@ import com.google.inject.Inject; import com.google.inject.Provider; -public class ChargerOccupancyTimeProfileCollectorProvider implements Provider { +public final class ChargerOccupancyTimeProfileCollectorProvider implements Provider { private final ChargingInfrastructure chargingInfrastructure; private final MatsimServices matsimServices; @Inject - public ChargerOccupancyTimeProfileCollectorProvider(ChargingInfrastructure chargingInfrastructure, MatsimServices matsimServices) { + ChargerOccupancyTimeProfileCollectorProvider(ChargingInfrastructure chargingInfrastructure, MatsimServices matsimServices) { this.chargingInfrastructure = chargingInfrastructure; this.matsimServices = matsimServices; } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerOccupancyXYDataCollector.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerOccupancyXYDataCollector.java index fa2dd8618aa..c0b1c5df506 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerOccupancyXYDataCollector.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerOccupancyXYDataCollector.java @@ -37,7 +37,7 @@ import com.google.inject.Inject; -public class ChargerOccupancyXYDataCollector implements MobsimInitializedListener, MobsimBeforeSimStepListener, MobsimBeforeCleanupListener { +public final class ChargerOccupancyXYDataCollector implements MobsimInitializedListener, MobsimBeforeSimStepListener, MobsimBeforeCleanupListener { private final ChargingInfrastructure chargingInfrastructure; private final MatsimServices matsimServices; @@ -45,7 +45,7 @@ public class ChargerOccupancyXYDataCollector implements MobsimInitializedListene private CompactCSVWriter writer; @Inject - public ChargerOccupancyXYDataCollector(ChargingInfrastructure chargingInfrastructure, MatsimServices matsimServices) { + ChargerOccupancyXYDataCollector(ChargingInfrastructure chargingInfrastructure, MatsimServices matsimServices) { this.chargingInfrastructure = chargingInfrastructure; this.matsimServices = matsimServices; } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerPowerCollector.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerPowerCollector.java index 14ffb1e84a6..1db79d2ae97 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerPowerCollector.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerPowerCollector.java @@ -53,7 +53,7 @@ /* * created by jbischoff, 26.10.2018 */ -public class ChargerPowerCollector +public final class ChargerPowerCollector implements ChargingStartEventHandler, ChargingEndEventHandler, MobsimScopeEventHandler, MobsimBeforeCleanupListener { @Inject @@ -65,6 +65,8 @@ public class ChargerPowerCollector @Inject private ElectricFleet fleet; + @Inject ChargerPowerCollector(){} // this forces instantiation via guice. kai, oct'23 + private record TimeCharge(double time, double charge) { } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerPowerTimeProfileCalculator.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerPowerTimeProfileCalculator.java index 78e7f6987ef..576d06d4a9e 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerPowerTimeProfileCalculator.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerPowerTimeProfileCalculator.java @@ -19,7 +19,7 @@ import com.google.inject.Inject; -public class ChargerPowerTimeProfileCalculator implements ChargingStartEventHandler, ChargingEndEventHandler { +public final class ChargerPowerTimeProfileCalculator implements ChargingStartEventHandler, ChargingEndEventHandler { private final Map, double[]> chargerProfiles = new HashMap<>(); private final Map, Double> chargingStartTimeMap = new HashMap<>(); @@ -35,7 +35,7 @@ public class ChargerPowerTimeProfileCalculator implements ChargingStartEventHand * @author mattiasingelstrom */ @Inject - public ChargerPowerTimeProfileCalculator(Config config) { + ChargerPowerTimeProfileCalculator(Config config) { int chargeTimeStep = ConfigUtils.addOrGetModule(config, EvConfigGroup.class).chargeTimeStep; qsimEndTime = ConfigUtils.addOrGetModule(config, QSimConfigGroup.class).getEndTime().orElse(0.0); timeDiscretizer = new TimeDiscretizer((int)Math.ceil(qsimEndTime), chargeTimeStep); diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerPowerTimeProfileView.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerPowerTimeProfileView.java index d0941954540..666a1abebe7 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerPowerTimeProfileView.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/ChargerPowerTimeProfileView.java @@ -8,10 +8,10 @@ import java.awt.*; import java.util.Map; -public class ChargerPowerTimeProfileView implements ProfileWriter.ProfileView { +final class ChargerPowerTimeProfileView implements ProfileWriter.ProfileView { private final ChargerPowerTimeProfileCalculator calculator; - public ChargerPowerTimeProfileView(ChargerPowerTimeProfileCalculator calculator) { + ChargerPowerTimeProfileView(ChargerPowerTimeProfileCalculator calculator) { this.calculator = calculator; } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/EnergyConsumptionCollector.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/EnergyConsumptionCollector.java index 4995a3ba41b..2f1a90c1d47 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/EnergyConsumptionCollector.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/EnergyConsumptionCollector.java @@ -56,6 +56,8 @@ public class EnergyConsumptionCollector implements DrivingEnergyConsumptionEvent private final Map, Double> energyConsumptionPerLink = new HashMap<>(); + @Inject EnergyConsumptionCollector(){} // so that class can only be instantiated via guice. kai, oct'23 + @Override public void handleEvent(DrivingEnergyConsumptionEvent event) { energyConsumptionPerLink.merge(event.getLinkId(), event.getEnergy(), Double::sum); diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/IndividualChargeTimeProfileCollectorProvider.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/IndividualChargeTimeProfileCollectorProvider.java index a623b04e6e8..44667aa3e84 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/IndividualChargeTimeProfileCollectorProvider.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/stats/IndividualChargeTimeProfileCollectorProvider.java @@ -39,13 +39,13 @@ import com.google.inject.Inject; import com.google.inject.Provider; -public class IndividualChargeTimeProfileCollectorProvider implements Provider { +public final class IndividualChargeTimeProfileCollectorProvider implements Provider { private final ElectricFleet evFleet; private final MatsimServices matsimServices; private final int maxVehicleColumns; @Inject - public IndividualChargeTimeProfileCollectorProvider(ElectricFleet evFleet, MatsimServices matsimServices, Config config) { + IndividualChargeTimeProfileCollectorProvider(ElectricFleet evFleet, MatsimServices matsimServices, Config config) { this.evFleet = evFleet; this.matsimServices = matsimServices; maxVehicleColumns = ConfigUtils.addOrGetModule(config, EvConfigGroup.class).numberOfIndividualTimeProfiles; diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/temperature/TemperatureChangeModule.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/temperature/TemperatureChangeModule.java index 697e0437ed2..2a4530061e2 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/temperature/TemperatureChangeModule.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/temperature/TemperatureChangeModule.java @@ -21,14 +21,29 @@ * created by jbischoff, 15.08.2018 */ +import com.google.inject.Singleton; import org.matsim.core.controler.AbstractModule; public class TemperatureChangeModule extends AbstractModule { @Override public void install() { - addMobsimListenerBinding().to(TemperatureManager.class).asEagerSingleton(); - bind(TemperatureServiceImpl.class).asEagerSingleton(); - bind(TemperatureService.class).to(TemperatureServiceImpl.class); - addEventHandlerBinding().to(TemperatureServiceImpl.class); + + addMobsimListenerBinding().to(TemperatureManager.class).in( Singleton.class ); + + bind(TemperatureServiceImpl.class).in( Singleton.class ); + bind(TemperatureService.class).to(TemperatureServiceImpl.class); + addEventHandlerBinding().to(TemperatureServiceImpl.class); + + // yyyy Shouldn't we think about just having a like + +// bind(TemperatureService.class).to(TemperatureServiceImpl.class)(.in( Singleton.class )); + + // and then make sure that the implementation registers itself? But how to actually achieve that? kai, oct'23 + + // I think that the answer to that last question is to bind the interface rather than the implementation, and have that further "upstairs" in the ev module: + // addEventHandlerBinding().to( TemperatureService.class ); + // for this, evidently, the interface needs to implement the right things (which it currently does not). + + } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/temperature/TemperatureManager.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/temperature/TemperatureManager.java index 74bdb5055b6..ffddbf850a6 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/temperature/TemperatureManager.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/temperature/TemperatureManager.java @@ -51,7 +51,7 @@ public class TemperatureManager implements MobsimBeforeSimStepListener, MobsimIn private final EventsManager events; @Inject - public TemperatureManager(Config config, EventsManager events) { + TemperatureManager(Config config, EventsManager events) { this.events = events; TemperatureChangeConfigGroup temperatureChangeConfigGroup = (TemperatureChangeConfigGroup)config.getModules() .get(TemperatureChangeConfigGroup.GROUP_NAME); diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/temperature/package-info.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/temperature/package-info.java new file mode 100644 index 00000000000..bab62cd2b51 --- /dev/null +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/temperature/package-info.java @@ -0,0 +1,4 @@ +/** + * I think that this is about ambient temperature. And it is here since charging may depend on ambient temperatur. + */ +package org.matsim.contrib.ev.temperature; diff --git a/contribs/ev/src/test/java/org/matsim/contrib/ev/charging/FastThenSlowChargingTest.java b/contribs/ev/src/test/java/org/matsim/contrib/ev/charging/FastThenSlowChargingTest.java index 66e8fd19a87..08eed4fe613 100644 --- a/contribs/ev/src/test/java/org/matsim/contrib/ev/charging/FastThenSlowChargingTest.java +++ b/contribs/ev/src/test/java/org/matsim/contrib/ev/charging/FastThenSlowChargingTest.java @@ -25,8 +25,8 @@ import org.junit.Test; import org.matsim.api.core.v01.Id; import org.matsim.contrib.ev.EvUnits; +import org.matsim.contrib.ev.fleet.ElectricFleetUtils; import org.matsim.contrib.ev.fleet.ElectricVehicle; -import org.matsim.contrib.ev.fleet.ElectricVehicleImpl; import org.matsim.contrib.ev.fleet.ElectricVehicleSpecification; import org.matsim.contrib.ev.infrastructure.Charger; import org.matsim.contrib.ev.infrastructure.ChargerSpecification; @@ -160,11 +160,11 @@ record TestEvSpecification(Id getId, Vehicle getMatsimVehicle, String g var specification = new TestEvSpecification(Id.create("ev_id", Vehicle.class), null, "vt", ImmutableList.of("ct"), EvUnits.kWh_to_J(capacity_kWh), charge_kWh / capacity_kWh); - return ElectricVehicleImpl.create(specification, ev -> (link, travelTime, linkEnterTime) -> { + return ElectricFleetUtils.create(specification, ev -> ( link, travelTime, linkEnterTime) -> { throw new UnsupportedOperationException(); }, ev -> (beginTime, duration, linkId) -> { throw new UnsupportedOperationException(); - }, FastThenSlowCharging::new); + }, FastThenSlowCharging::new ); } @Test diff --git a/contribs/ev/src/test/java/org/matsim/contrib/ev/charging/VariableSpeedChargingTest.java b/contribs/ev/src/test/java/org/matsim/contrib/ev/charging/VariableSpeedChargingTest.java index 06091cae47c..1f0c78ffab9 100644 --- a/contribs/ev/src/test/java/org/matsim/contrib/ev/charging/VariableSpeedChargingTest.java +++ b/contribs/ev/src/test/java/org/matsim/contrib/ev/charging/VariableSpeedChargingTest.java @@ -25,7 +25,7 @@ import org.junit.Test; import org.matsim.api.core.v01.Id; import org.matsim.contrib.ev.EvUnits; -import org.matsim.contrib.ev.fleet.ElectricVehicleImpl; +import org.matsim.contrib.ev.fleet.ElectricFleetUtils; import org.matsim.contrib.ev.fleet.ElectricVehicleSpecification; import org.matsim.contrib.ev.infrastructure.Charger; import org.matsim.contrib.ev.infrastructure.ChargerSpecification; @@ -96,11 +96,11 @@ record TestEvSpecification(Id getId, Vehicle getMatsimVehicle, String g .plugCount(1) .build(); - var electricVehicle = ElectricVehicleImpl.create(specification, ev -> (link, travelTime, linkEnterTime) -> { + var electricVehicle = ElectricFleetUtils.create(specification, ev -> ( link, travelTime, linkEnterTime) -> { throw new UnsupportedOperationException(); }, ev -> (beginTime, duration, linkId) -> { throw new UnsupportedOperationException(); - }, VariableSpeedCharging::createForTesla); + }, VariableSpeedCharging::createForTesla ); Assertions.assertThat(electricVehicle.getChargingPower().calcChargingPower(charger)) .isCloseTo(EvUnits.kW_to_W(expectedChargingPower_kW), Percentage.withPercentage(1e-13)); } diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryEndEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryEndEvent.java index c49c04aa533..c02717031fa 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryEndEvent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryEndEvent.java @@ -84,7 +84,7 @@ public static CarrierShipmentDeliveryEndEvent convert(GenericEvent event) { Id shipmentTo = Id.createLinkId(attributes.get(ATTRIBUTE_LINK)); int size = Integer.parseInt(attributes.get(CarrierEventAttributes.ATTRIBUTE_CAPACITYDEMAND)); CarrierShipment shipment = CarrierShipment.Builder.newInstance(shipmentId, null, shipmentTo, size) - .setDeliveryServiceTime(Double.parseDouble(attributes.get(CarrierEventAttributes.ATTRIBUTE_SERVICE_DURATION))) + .setDeliveryServiceTime(Double.parseDouble(attributes.get(CarrierEventAttributes.ATTRIBUTE_DROPOFF_DURATION))) .build(); Id vehicleId = Id.createVehicleId(attributes.get(ATTRIBUTE_VEHICLE)); return new CarrierShipmentDeliveryEndEvent(time, carrierId, shipment, vehicleId); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryStartEvent.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryStartEvent.java index e12222973c1..43cf21fc752 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryStartEvent.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/CarrierShipmentDeliveryStartEvent.java @@ -85,7 +85,7 @@ public static CarrierShipmentDeliveryStartEvent convert(GenericEvent event) { Id shipmentTo = Id.createLinkId(attributes.get(ATTRIBUTE_LINK)); int size = Integer.parseInt(attributes.get(ATTRIBUTE_CAPACITYDEMAND)); CarrierShipment shipment = CarrierShipment.Builder.newInstance(shipmentId, null, shipmentTo, size) - .setDeliveryServiceTime(Double.parseDouble(attributes.get(ATTRIBUTE_SERVICE_DURATION))) + .setDeliveryServiceTime(Double.parseDouble(attributes.get(ATTRIBUTE_DROPOFF_DURATION))) .build(); Id vehicleId = Id.createVehicleId(attributes.get(ATTRIBUTE_VEHICLE)); return new CarrierShipmentDeliveryStartEvent(time, carrierId, shipment, vehicleId); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightServiceEndEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierServiceEndEventHandler.java similarity index 95% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightServiceEndEventHandler.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierServiceEndEventHandler.java index 65db8298b92..11ccfde0372 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightServiceEndEventHandler.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierServiceEndEventHandler.java @@ -25,7 +25,7 @@ import org.matsim.core.events.handler.EventHandler; import org.matsim.freight.carriers.events.CarrierServiceEndEvent; -public interface FreightServiceEndEventHandler extends EventHandler{ +public interface CarrierServiceEndEventHandler extends EventHandler{ void handleEvent( CarrierServiceEndEvent event ); } diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightServiceStartEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierServiceStartEventHandler.java similarity index 96% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightServiceStartEventHandler.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierServiceStartEventHandler.java index 78534b0337e..a8ea55c13e8 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightServiceStartEventHandler.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierServiceStartEventHandler.java @@ -25,7 +25,7 @@ import org.matsim.freight.carriers.events.CarrierServiceStartEvent; -public interface FreightServiceStartEventHandler extends EventHandler { +public interface CarrierServiceStartEventHandler extends EventHandler { void handleEvent( CarrierServiceStartEvent event ); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightShipmentDeliveryEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierShipmentDeliveryEndEventHandler.java similarity index 95% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightShipmentDeliveryEventHandler.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierShipmentDeliveryEndEventHandler.java index 858a91fdca5..b2cc8ff31dc 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightShipmentDeliveryEventHandler.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierShipmentDeliveryEndEventHandler.java @@ -30,7 +30,7 @@ * @author sschroeder * */ -public interface FreightShipmentDeliveryEventHandler extends EventHandler { +public interface CarrierShipmentDeliveryEndEventHandler extends EventHandler { void handleEvent(CarrierShipmentDeliveryEndEvent event); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierShipmentDeliveryStartEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierShipmentDeliveryStartEventHandler.java new file mode 100644 index 00000000000..df8a7b9785a --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierShipmentDeliveryStartEventHandler.java @@ -0,0 +1,37 @@ +/* + * *********************************************************************** * + * project: org.matsim.* + * *********************************************************************** * + * * + * copyright : (C) by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** + * + */ + +package org.matsim.freight.carriers.events.eventhandler; + +import org.matsim.core.events.handler.EventHandler; +import org.matsim.freight.carriers.events.CarrierShipmentDeliveryStartEvent; + +/** + * Interface to listen to shipmentDeliveredEvents. + * + * @author sschroeder + * + */ +public interface CarrierShipmentDeliveryStartEventHandler extends EventHandler { + + void handleEvent(CarrierShipmentDeliveryStartEvent event); + +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightShipmentPickupEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierShipmentPickupEndEventHandler.java similarity index 95% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightShipmentPickupEventHandler.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierShipmentPickupEndEventHandler.java index 126942b432f..4c7282c29c7 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightShipmentPickupEventHandler.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierShipmentPickupEndEventHandler.java @@ -30,6 +30,6 @@ * @author sschroeder * */ -public interface FreightShipmentPickupEventHandler extends EventHandler { +public interface CarrierShipmentPickupEndEventHandler extends EventHandler { void handleEvent(CarrierShipmentPickupEndEvent event); } diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierShipmentPickupStartEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierShipmentPickupStartEventHandler.java new file mode 100644 index 00000000000..79c2426f023 --- /dev/null +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierShipmentPickupStartEventHandler.java @@ -0,0 +1,35 @@ +/* + * *********************************************************************** * + * project: org.matsim.* + * *********************************************************************** * + * * + * copyright : (C) by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** + * + */ + +package org.matsim.freight.carriers.events.eventhandler; + +import org.matsim.core.events.handler.EventHandler; +import org.matsim.freight.carriers.events.CarrierShipmentPickupStartEvent; + +/** + * Interface to listen to shipmentPickedUpEvents. + * + * @author sschroeder + * + */ +public interface CarrierShipmentPickupStartEventHandler extends EventHandler { + void handleEvent(CarrierShipmentPickupStartEvent event); +} diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightTourEndEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourEndEventHandler.java similarity index 95% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightTourEndEventHandler.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourEndEventHandler.java index 7a91f767c4d..2d30ce4d70c 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightTourEndEventHandler.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourEndEventHandler.java @@ -25,7 +25,7 @@ import org.matsim.freight.carriers.events.CarrierTourEndEvent; -public interface FreightTourEndEventHandler extends EventHandler { +public interface CarrierTourEndEventHandler extends EventHandler { void handleEvent( CarrierTourEndEvent event ); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightTourStartEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourStartEventHandler.java similarity index 95% rename from contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightTourStartEventHandler.java rename to contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourStartEventHandler.java index 21b14f86ce0..5f4b26ce4bb 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/FreightTourStartEventHandler.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/CarrierTourStartEventHandler.java @@ -25,7 +25,7 @@ import org.matsim.freight.carriers.events.CarrierTourStartEvent; -public interface FreightTourStartEventHandler extends EventHandler { +public interface CarrierTourStartEventHandler extends EventHandler { void handleEvent( CarrierTourStartEvent event ); diff --git a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/Vehicle2CarrierEventHandler.java b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/Vehicle2CarrierEventHandler.java index e116ab1493e..bc9236decbf 100644 --- a/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/Vehicle2CarrierEventHandler.java +++ b/contribs/freight/src/main/java/org/matsim/freight/carriers/events/eventhandler/Vehicle2CarrierEventHandler.java @@ -36,7 +36,7 @@ * * @author kturner */ -public final class Vehicle2CarrierEventHandler implements FreightTourStartEventHandler, FreightTourEndEventHandler { +public final class Vehicle2CarrierEventHandler implements CarrierTourStartEventHandler, CarrierTourEndEventHandler { // Comment from Janek (in https://github.com/matsim-org/matsim-libs/pull/2128) diff --git a/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierEventsReadersTest.java b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierEventsReadersTest.java new file mode 100644 index 00000000000..37a4cabaf82 --- /dev/null +++ b/contribs/freight/src/test/java/org/matsim/freight/carriers/CarrierEventsReadersTest.java @@ -0,0 +1,251 @@ +/* + * *********************************************************************** * + * project: org.matsim.* + * *********************************************************************** * + * * + * copyright : (C) 2023 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** * + */ + +package org.matsim.freight.carriers; + +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.events.Event; +import org.matsim.api.core.v01.network.Link; +import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.config.groups.ControllerConfigGroup; +import org.matsim.core.events.EventsUtils; +import org.matsim.core.events.algorithms.EventWriterXML; +import org.matsim.freight.carriers.events.*; +import org.matsim.freight.carriers.events.eventhandler.*; +import org.matsim.testcases.MatsimTestUtils; +import org.matsim.testcases.utils.EventsCollector; +import org.matsim.vehicles.Vehicle; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.List; + + +/** + * @author Kai Martins-Turner (kturner) + * @author Niclas Richter (nixlaos) + */ +public class CarrierEventsReadersTest { + + + @Rule + public final MatsimTestUtils utils = new MatsimTestUtils(); + + private final Id linkId = Id.createLinkId("demoLink"); + private final Id linkId2 = Id.createLinkId("demoLink2"); + private final Id carrierId = Id.create("testCarrier", Carrier.class); + private final Id vehicleId = Id.createVehicleId("myVehicle"); + + private final Id tourId = Id.create("myCarrierTour", Tour.class); + private final CarrierService service = CarrierService.Builder.newInstance(Id.create("service42", CarrierService.class), linkId2 ).build(); + private final CarrierShipment shipment = CarrierShipment.Builder.newInstance(Id.create("shipment11", CarrierShipment.class), linkId, linkId2,7 ).build(); + + private final List carrierEvents = List.of( + new CarrierTourStartEvent(10, carrierId, linkId, vehicleId, tourId), + new CarrierTourEndEvent(500, carrierId, linkId, vehicleId, tourId), + new CarrierServiceStartEvent(20, carrierId, service, vehicleId), + new CarrierServiceEndEvent(25, carrierId, service, vehicleId), + new CarrierShipmentPickupStartEvent(100, carrierId, shipment, vehicleId), + new CarrierShipmentPickupEndEvent(115, carrierId, shipment, vehicleId), + new CarrierShipmentDeliveryStartEvent(210, carrierId, shipment, vehicleId), + new CarrierShipmentDeliveryEndEvent(225, carrierId, shipment, vehicleId) + ); + + @Test + public void testWriteReadServiceBasedEvents() { + EventsManager eventsManager1 = EventsUtils.createEventsManager(); + EventsManager eventsManager2 = EventsUtils.createEventsManager(); + EventsCollector collector1 = new EventsCollector(); + EventsCollector collector2 = new EventsCollector(); + + eventsManager1.addHandler(collector1); + eventsManager1.initProcessing(); + CarrierEventsReaders.createEventsReader(eventsManager1) + .readFile(utils.getClassInputDirectory() + "serviceBasedEvents.xml"); + eventsManager1.finishProcessing(); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + EventWriterXML writer = new EventWriterXML(outputStream); + collector1.getEvents().forEach(writer::handleEvent); + writer.closeFile(); + + eventsManager2.addHandler(collector2); + eventsManager2.initProcessing(); + CarrierEventsReaders.createEventsReader(eventsManager2) + .readStream(new ByteArrayInputStream(outputStream.toByteArray()), ControllerConfigGroup.EventsFileFormat.xml); + eventsManager2.finishProcessing(); + + Assert.assertEquals(collector1.getEvents(), collector2.getEvents()); + } + + + @Test + public void testReadServiceBasedEvents() { + + EventsManager eventsManager = EventsUtils.createEventsManager(); + TestEventHandlerTours eventHandlerTours = new TestEventHandlerTours(); + TestEventHandlerServices eventHandlerServices = new TestEventHandlerServices(); + + eventsManager.addHandler(eventHandlerTours); + eventsManager.addHandler(eventHandlerServices); + eventsManager.initProcessing(); + CarrierEventsReaders.createEventsReader(eventsManager) + .readFile(utils.getClassInputDirectory() + "serviceBasedEvents.xml"); + eventsManager.finishProcessing(); + + Assert.assertEquals("Number of tour related carrier events is not correct", 4 , eventHandlerTours.handledEvents.size()); + Assert.assertEquals("Number of service related carrier events is not correct", 14 , eventHandlerServices.handledEvents.size()); + } + + @Test + public void testWriteReadShipmentBasedEvents() { + EventsManager eventsManager1 = EventsUtils.createEventsManager(); + EventsManager eventsManager2 = EventsUtils.createEventsManager(); + EventsCollector collector1 = new EventsCollector(); + EventsCollector collector2 = new EventsCollector(); + + eventsManager1.addHandler(collector1); + eventsManager1.initProcessing(); + CarrierEventsReaders.createEventsReader(eventsManager1) + .readFile(utils.getClassInputDirectory() + "shipmentBasedEvents.xml"); + eventsManager1.finishProcessing(); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + EventWriterXML writer = new EventWriterXML(outputStream); + collector1.getEvents().forEach(writer::handleEvent); + writer.closeFile(); + + eventsManager2.addHandler(collector2); + eventsManager2.initProcessing(); + CarrierEventsReaders.createEventsReader(eventsManager2) + .readStream(new ByteArrayInputStream(outputStream.toByteArray()), ControllerConfigGroup.EventsFileFormat.xml); + eventsManager2.finishProcessing(); + + Assert.assertEquals(collector1.getEvents(), collector2.getEvents()); + } + + @Test + public void testReadShipmentBasedEvents() { + + EventsManager eventsManager = EventsUtils.createEventsManager(); + TestEventHandlerTours eventHandlerTours = new TestEventHandlerTours(); + TestEventHandlerShipments testEventHandlerShipments = new TestEventHandlerShipments(); + + eventsManager.addHandler(eventHandlerTours); + eventsManager.addHandler(testEventHandlerShipments); + eventsManager.initProcessing(); + CarrierEventsReaders.createEventsReader(eventsManager) + .readFile(utils.getClassInputDirectory() + "shipmentBasedEvents.xml"); + eventsManager.finishProcessing(); + + Assert.assertEquals("Number of tour related carrier events is not correct", 2 , eventHandlerTours.handledEvents.size()); + Assert.assertEquals("Number of shipments related carrier events is not correct", 20 , testEventHandlerShipments.handledEvents.size()); + } + + + /** + * This test is testing the reader with some locally created events (see above). + * This test is inspired by the DrtEventsReaderTest from michalm. + */ + @Test + public void testReader() { + var outputStream = new ByteArrayOutputStream(); + EventWriterXML writer = new EventWriterXML(outputStream); + carrierEvents.forEach(writer::handleEvent); + writer.closeFile(); + + EventsManager eventsManager = EventsUtils.createEventsManager(); + TestEventHandlerTours eventHandlerTours = new TestEventHandlerTours(); + TestEventHandlerServices eventHandlerServices = new TestEventHandlerServices(); + TestEventHandlerShipments eventHandlerShipments = new TestEventHandlerShipments(); + + eventsManager.addHandler(eventHandlerTours); + eventsManager.addHandler(eventHandlerServices); + eventsManager.addHandler(eventHandlerShipments); + + eventsManager.initProcessing(); + CarrierEventsReaders.createEventsReader(eventsManager) + .readStream(new ByteArrayInputStream(outputStream.toByteArray()), + ControllerConfigGroup.EventsFileFormat.xml); + eventsManager.finishProcessing(); + + var handledEvents = new ArrayList(); + handledEvents.addAll(eventHandlerTours.handledEvents); + handledEvents.addAll(eventHandlerServices.handledEvents); + handledEvents.addAll(eventHandlerShipments.handledEvents); + + //Please note: This test is sensitive to the order of events as they are added in carrierEvents (input) and the resukts of the handler... + Assert.assertArrayEquals(carrierEvents.toArray(), handledEvents.toArray()); + } + + private static class TestEventHandlerTours + implements CarrierTourStartEventHandler, CarrierTourEndEventHandler { + private final List handledEvents = new ArrayList<>(); + + + @Override public void handleEvent(CarrierTourEndEvent event) { + handledEvents.add(event); + } + + @Override public void handleEvent(CarrierTourStartEvent event) { + handledEvents.add(event); + } + } + + private static class TestEventHandlerServices + implements CarrierServiceStartEventHandler, CarrierServiceEndEventHandler { + private final List handledEvents = new ArrayList<>(); + + @Override public void handleEvent(CarrierServiceEndEvent event) { + handledEvents.add(event); + } + + @Override public void handleEvent(CarrierServiceStartEvent event) { + handledEvents.add(event); + } + + } + + private static class TestEventHandlerShipments + implements CarrierShipmentDeliveryStartEventHandler, CarrierShipmentDeliveryEndEventHandler, CarrierShipmentPickupStartEventHandler, CarrierShipmentPickupEndEventHandler { + private final List handledEvents = new ArrayList<>(); + + + @Override public void handleEvent(CarrierShipmentDeliveryEndEvent event) { + handledEvents.add(event); + } + + @Override public void handleEvent(CarrierShipmentPickupEndEvent event) { + handledEvents.add(event); + } + + @Override public void handleEvent(CarrierShipmentDeliveryStartEvent event) { + handledEvents.add(event); + } + + @Override public void handleEvent(CarrierShipmentPickupStartEvent event) { + handledEvents.add(event); + } + } +} diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierEventsReadersTest/serviceBasedEvents.xml b/contribs/freight/test/input/org/matsim/freight/carriers/CarrierEventsReadersTest/serviceBasedEvents.xml new file mode 100644 index 00000000000..b4121096264 --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/carriers/CarrierEventsReadersTest/serviceBasedEvents.xml @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/CarrierEventsReadersTest/shipmentBasedEvents.xml b/contribs/freight/test/input/org/matsim/freight/carriers/CarrierEventsReadersTest/shipmentBasedEvents.xml new file mode 100644 index 00000000000..ca675a9bcbf --- /dev/null +++ b/contribs/freight/test/input/org/matsim/freight/carriers/CarrierEventsReadersTest/shipmentBasedEvents.xml @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contribs/hybridsim/pom.xml b/contribs/hybridsim/pom.xml index 2a8fffb488b..fe40487e7f4 100644 --- a/contribs/hybridsim/pom.xml +++ b/contribs/hybridsim/pom.xml @@ -11,7 +11,7 @@ 3.24.4 - 1.58.0 + 1.59.0 diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/InformedModeChoiceModule.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/InformedModeChoiceModule.java index d151624afe2..a6229390386 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/InformedModeChoiceModule.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/InformedModeChoiceModule.java @@ -167,7 +167,7 @@ public > Builder withFixedCosts(Class> Builder withLegEstimator(Class> estimator, Class> option, + public > Builder withLegEstimator(Class> estimator, Class> option, String... modes) { for (String mode : modes) { diff --git a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanModelService.java b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanModelService.java index 4930197c262..93c2ca21a0f 100644 --- a/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanModelService.java +++ b/contribs/informed-mode-choice/src/main/java/org/matsim/modechoice/PlanModelService.java @@ -157,6 +157,7 @@ public List allowedModes(PlanModel planModel) { /** * Calculate the estimates for all options. Note that plan model has to be routed before computing estimates. */ + @SuppressWarnings("rawtypes") public void calculateEstimates(EstimatorContext context, PlanModel planModel) { for (Map.Entry> e : planModel.getEstimates().entrySet()) { @@ -208,7 +209,7 @@ public void calculateEstimates(EstimatorContext context, PlanModel planModel) { if (tripEst != null && legMode.equals(c.getMode())) continue; - LegEstimator> legEst = (LegEstimator>) legEstimators.get(legMode); + LegEstimator legEst = legEstimators.get(legMode); if (legEst == null) throw new IllegalStateException("No leg estimator defined for mode: " + legMode); diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/NearestParkingDynLeg.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/NearestParkingDynLeg.java index 96bbd7928c5..a5f4cdcf143 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/NearestParkingDynLeg.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/NearestParkingDynLeg.java @@ -1,20 +1,21 @@ package org.matsim.contrib.parking.parkingsearch.DynAgent; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Leg; import org.matsim.api.core.v01.population.Plan; -import org.matsim.contrib.parking.parkingsearch.events.RemoveParkingActivityEvent; -import org.matsim.contrib.parking.parkingsearch.events.ReserveParkingLocationEvent; -import org.matsim.contrib.parking.parkingsearch.events.SelectNewParkingLocationEvent; -import org.matsim.contrib.parking.parkingsearch.events.StartParkingSearchEvent; +import org.matsim.contrib.parking.parkingsearch.ParkingUtils; +import org.matsim.contrib.parking.parkingsearch.events.*; import org.matsim.contrib.parking.parkingsearch.manager.FacilityBasedParkingManager; import org.matsim.contrib.parking.parkingsearch.manager.ParkingSearchManager; import org.matsim.contrib.parking.parkingsearch.search.NearestParkingSpotSearchLogic; import org.matsim.contrib.parking.parkingsearch.search.ParkingSearchLogic; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.mobsim.framework.MobsimTimer; +import org.matsim.core.population.PopulationUtils; import org.matsim.core.population.routes.NetworkRoute; import org.matsim.core.utils.collections.Tuple; import org.matsim.vehicles.Vehicle; @@ -26,6 +27,7 @@ */ public class NearestParkingDynLeg extends ParkingDynLeg { private boolean parkingAtEndOfLeg = true; + private boolean passangerInteractionAtParkingFacilityAtEndOfLeg = false; private boolean reachedDestinationWithoutParking = false; private boolean alreadyReservedParking = false; private boolean driveToBaseWithoutParking = false; @@ -34,18 +36,19 @@ public class NearestParkingDynLeg extends ParkingDynLeg { private final int planIndexNextActivity; private Plan plan; private Id nextSelectedParkingLink = null; + protected static final Logger log = LogManager.getLogger(NearestParkingDynLeg.class); public NearestParkingDynLeg(Leg currentPlannedLeg, NetworkRoute route, Plan plan, int planIndexNextActivity, ParkingSearchLogic logic, ParkingSearchManager parkingManager, Id vehicleId, MobsimTimer timer, EventsManager events) { super(currentPlannedLeg.getMode(), route, logic, parkingManager, vehicleId, timer, events); this.followingActivity = (Activity) plan.getPlanElements().get(planIndexNextActivity); - followingActivity.setStartTime(timer.getTimeOfDay()); this.currentPlannedLeg = currentPlannedLeg; this.plan = plan; this.planIndexNextActivity = planIndexNextActivity; - if (followingActivity.getAttributes().getAsMap().containsKey("parking") && followingActivity.getAttributes().getAttribute("parking").equals( - "noParking")) + if (ParkingUtils.checkIfActivityHasNoParking(followingActivity)) parkingAtEndOfLeg = false; + if (ParkingUtils.checkIfActivityHasPassengerInteraction(followingActivity)) + passangerInteractionAtParkingFacilityAtEndOfLeg = true; } @Override @@ -85,7 +88,7 @@ public void movedOverNode(Id newLinkId) { @Override public Id getNextLinkId() { - if (!parkingMode && parkingAtEndOfLeg) { + if (!passangerInteractionAtParkingFacilityAtEndOfLeg && (!parkingMode && parkingAtEndOfLeg)) { parkingMode = true; this.events.processEvent(new StartParkingSearchEvent(timer.getTimeOfDay(), vehicleId, currentLinkId)); } @@ -98,12 +101,18 @@ public Id getNextLinkId() { return linkIds.get(currentLinkIdx + 1); } else { + if (passangerInteractionAtParkingFacilityAtEndOfLeg && !hasFoundParking && followingActivity.getLinkId().equals(currentLinkId)) { + createWaitingActivityUntilPassengerInteractionIsPossible(currentLinkId, vehicleId, timer.getTimeOfDay()); + this.events + .processEvent(new StartWaitingForParkingEvent(timer.getTimeOfDay(), vehicleId, currentLinkId)); + } if (hasFoundParking || reachedDestinationWithoutParking) { // easy, we can just park where at our destination link - if (hasFoundParking) { + if (hasFoundParking && !passangerInteractionAtParkingFacilityAtEndOfLeg) { + //calculate parkingTime for parking_activity double parkingDuration; double expectedDrivingDurationToPickup; - double drivingDurationFromDropOff = timer.getTimeOfDay() - currentPlannedLeg.getDepartureTime().seconds(); + double drivingDurationFromGetOff = timer.getTimeOfDay() - currentPlannedLeg.getDepartureTime().seconds(); if (nextSelectedParkingLink.equals(currentLinkId)) { expectedDrivingDurationToPickup = ((NearestParkingSpotSearchLogic) this.logic).getExpectedTravelTime( @@ -112,7 +121,9 @@ public Id getNextLinkId() { expectedDrivingDurationToPickup = ((NearestParkingSpotSearchLogic) this.logic).getExpectedTravelTime( currentPlannedLeg.getRoute().getStartLinkId(), timer.getTimeOfDay(), currentLinkId); } - parkingDuration = followingActivity.getMaximumDuration().seconds() - drivingDurationFromDropOff - expectedDrivingDurationToPickup; + parkingDuration = followingActivity.getMaximumDuration().seconds() + - drivingDurationFromGetOff - expectedDrivingDurationToPickup + - ((FacilityBasedParkingManager) parkingManager).getParkStageActivityDuration(); followingActivity.setMaximumDuration(parkingDuration); } this.logic.reset(); @@ -125,10 +136,19 @@ public Id getNextLinkId() { } } // need to find the next link - double nextPickupTime = followingActivity.getStartTime().seconds() + followingActivity.getMaximumDuration().seconds(); - double maxParkingDuration = followingActivity.getMaximumDuration().seconds() - (followingActivity.getStartTime().seconds() - timer.getTimeOfDay()); + double nextPickupTime; + double maxParkingDuration; + if (passangerInteractionAtParkingFacilityAtEndOfLeg){ + nextPickupTime = 0.; + maxParkingDuration = followingActivity.getMaximumDuration().seconds(); + } + else { + nextPickupTime = currentPlannedLeg.getDepartureTime().seconds() + followingActivity.getMaximumDuration().seconds(); + maxParkingDuration = nextPickupTime - timer.getTimeOfDay(); + } Id nextLinkId = ((NearestParkingSpotSearchLogic) this.logic).getNextLink(currentLinkId, route.getEndLinkId(), vehicleId, mode, - timer.getTimeOfDay(), maxParkingDuration, nextPickupTime); + timer.getTimeOfDay(), maxParkingDuration, nextPickupTime, passangerInteractionAtParkingFacilityAtEndOfLeg, + followingActivity.getCoord()); if (((NearestParkingSpotSearchLogic) this.logic).isNextParkingActivitySkipped() && parkingAtEndOfLeg) { removeNextActivityAndFollowingLeg(); parkingAtEndOfLeg = false; @@ -163,9 +183,19 @@ public Id getNextLinkId() { } } + private void createWaitingActivityUntilPassengerInteractionIsPossible(Id newLinkId, Id vehicleId, double now) { + Activity waitingActivity = PopulationUtils.createActivityFromLinkId(ParkingUtils.WaitingForParkingActivityType, newLinkId); + ParkingUtils.setNoParkingForActivity(waitingActivity); + plan.getPlanElements().add(planIndexNextActivity, waitingActivity); + hasFoundParking = true; + ((FacilityBasedParkingManager) parkingManager).addVehicleForWaitingForParking(newLinkId, vehicleId, now); + } + private void removeNextActivityAndFollowingLeg() { plan.getPlanElements().remove(planIndexNextActivity); plan.getPlanElements().remove(planIndexNextActivity); +// log.info( +// plan.getPerson().getId().toString() + ": Parking activity after getOff point '" + ((Activity)plan.getPlanElements().get(planIndexNextActivity - 2)).getType() + "' is removed, because no parking facility was found."); } public boolean driveToBaseWithoutParking() { diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/BenensonParkingAgentLogic.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/BenensonParkingAgentLogic.java index c799cbc1355..381bfd331d2 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/BenensonParkingAgentLogic.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/BenensonParkingAgentLogic.java @@ -1,5 +1,5 @@ /** - * + * */ package org.matsim.contrib.parking.parkingsearch.DynAgent.agentLogic; @@ -9,7 +9,6 @@ import org.matsim.api.core.v01.population.Route; import org.matsim.contrib.dynagent.DynAction; import org.matsim.contrib.parking.parkingsearch.DynAgent.BenensonDynLeg; -import org.matsim.contrib.parking.parkingsearch.DynAgent.agentLogic.ParkingAgentLogic; import org.matsim.contrib.parking.parkingsearch.manager.ParkingSearchManager; import org.matsim.contrib.parking.parkingsearch.manager.vehicleteleportationlogic.VehicleTeleportationLogic; import org.matsim.contrib.parking.parkingsearch.routing.ParkingRouter; @@ -29,37 +28,37 @@ public class BenensonParkingAgentLogic extends ParkingAgentLogic { /** * @param plan * @param parkingManager - * @param walkLegFactory + * @param walkRouter * @param parkingRouter * @param events * @param parkingLogic * @param timer * @param teleportationLogic */ - - + + public BenensonParkingAgentLogic(Plan plan, ParkingSearchManager parkingManager, RoutingModule walkRouter, Network network, ParkingRouter parkingRouter, EventsManager events, ParkingSearchLogic parkingLogic, MobsimTimer timer, VehicleTeleportationLogic teleportationLogic, ParkingSearchConfigGroup configGroup) { super(plan, parkingManager, walkRouter, network, parkingRouter, events, parkingLogic, timer, teleportationLogic, configGroup); } - + @Override protected DynAction nextStateAfterUnParkActivity(DynAction oldAction, double now) { // we have unparked, now we need to get going by car again. - + Leg currentPlannedLeg = (Leg) currentPlanElement; Route plannedRoute = currentPlannedLeg.getRoute(); NetworkRoute actualRoute = this.parkingRouter.getRouteFromParkingToDestination(plannedRoute.getEndLinkId(), now, agent.getCurrentLinkId()); - if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now))||(isinitialLocation)){ + if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now))||(isInitialLocation)){ this.lastParkActionState = LastParkActionState.CARTRIP; - isinitialLocation = false; + isInitialLocation = false; Leg currentLeg = (Leg) this.currentPlanElement; //this could be Car, Carsharing, Motorcylce, or whatever else mode we have, so we want our leg to reflect this. return new BenensonDynLeg(currentLeg.getMode(), actualRoute, parkingLogic, parkingManager, currentlyAssignedVehicleId, timer, events); } else throw new RuntimeException("parking location mismatch"); - + } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/MemoryBasedParkingAgentLogic.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/MemoryBasedParkingAgentLogic.java index dbe7b937923..b7358bc6a39 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/MemoryBasedParkingAgentLogic.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/MemoryBasedParkingAgentLogic.java @@ -1,5 +1,5 @@ /** - * + * */ package org.matsim.contrib.parking.parkingsearch.DynAgent.agentLogic; @@ -31,22 +31,22 @@ public MemoryBasedParkingAgentLogic(Plan plan, ParkingSearchManager parkingManag super(plan, parkingManager, walkRouter, network, parkingRouter, events, parkingLogic, timer, teleportationLogic, configGroup); } - + @Override protected DynAction nextStateAfterUnParkActivity(DynAction oldAction, double now) { // we have unparked, now we need to get going by car again. - + Leg currentPlannedLeg = (Leg) currentPlanElement; Route plannedRoute = currentPlannedLeg.getRoute(); NetworkRoute actualRoute = this.parkingRouter.getRouteFromParkingToDestination(plannedRoute.getEndLinkId(), now, agent.getCurrentLinkId()); - if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now))||(isinitialLocation)){ + if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now))||(isInitialLocation)){ this.lastParkActionState = LastParkActionState.CARTRIP; - isinitialLocation = false; + isInitialLocation = false; Leg currentLeg = (Leg) this.currentPlanElement; //this could be Car, Carsharing, Motorcylce, or whatever else mode we have, so we want our leg to reflect this. return new DistanceMemoryDynLeg(currentLeg.getMode(), actualRoute, parkingLogic, parkingManager, currentlyAssignedVehicleId, timer, events); } else throw new RuntimeException("parking location mismatch"); - + } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/NearestParkingSpotAgentLogic.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/NearestParkingSpotAgentLogic.java index faec3310574..f3a7e671b14 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/NearestParkingSpotAgentLogic.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/NearestParkingSpotAgentLogic.java @@ -10,6 +10,7 @@ import org.matsim.contrib.dynagent.StaticPassengerDynLeg; import org.matsim.contrib.parking.parkingsearch.DynAgent.NearestParkingDynLeg; import org.matsim.contrib.parking.parkingsearch.ParkingUtils; +import org.matsim.contrib.parking.parkingsearch.manager.FacilityBasedParkingManager; import org.matsim.contrib.parking.parkingsearch.manager.ParkingSearchManager; import org.matsim.contrib.parking.parkingsearch.manager.vehicleteleportationlogic.VehicleTeleportationLogic; import org.matsim.contrib.parking.parkingsearch.routing.ParkingRouter; @@ -54,50 +55,35 @@ public DynAction computeNextAction(DynAction oldAction, double now) { if (lastParkActionState.equals(LastParkActionState.CARTRIP) && ((NearestParkingDynLeg) oldAction).driveToBaseWithoutParking()) this.lastParkActionState = LastParkActionState.WALKFROMPARK; - switch (lastParkActionState) { - case ACTIVITY: - return nextStateAfterActivity(oldAction, now); - - case CARTRIP: - return nextStateAfterCarTrip(oldAction, now); - - case NONCARTRIP: - return nextStateAfterNonCarTrip(oldAction, now); - - case PARKACTIVITY: - return nextStateAfterParkActivity(oldAction, now); - - case UNPARKACTIVITY: - return nextStateAfterUnParkActivity(oldAction, now); - - case WALKFROMPARK: - return nextStateAfterWalkFromPark(oldAction, now); - - case WALKTOPARK: - return nextStateAfterWalkToPark(oldAction, now); - - } - throw new RuntimeException("unreachable code"); - } + return switch (lastParkActionState) { + case ACTIVITY -> nextStateAfterActivity(oldAction, now); + case CARTRIP -> nextStateAfterCarTrip(oldAction, now); + case NONCARTRIP -> nextStateAfterNonCarTrip(oldAction, now); + case PARKACTIVITY -> nextStateAfterParkActivity(oldAction, now); + case UNPARKACTIVITY -> nextStateAfterUnParkActivity(oldAction, now); + case WALKFROMPARK -> nextStateAfterWalkFromPark(oldAction, now); + case WALKTOPARK -> nextStateAfterWalkToPark(oldAction, now); + }; + } @Override protected DynAction nextStateAfterUnParkActivity(DynAction oldAction, double now) { // we have unparked, now we need to get going by car again. Leg currentPlannedLeg = (Leg) currentPlanElement; + currentPlannedLeg.setDepartureTime(timer.getTimeOfDay()); Route plannedRoute = currentPlannedLeg.getRoute(); NetworkRoute actualRoute = this.parkingRouter.getRouteFromParkingToDestination(plannedRoute.getEndLinkId(), now, agent.getCurrentLinkId()); actualRoute.setVehicleId(currentlyAssignedVehicleId); if (!plannedRoute.getStartLinkId().equals(actualRoute.getStartLinkId())) currentPlannedLeg.setRoute(actualRoute); - if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now)) || (isinitialLocation)) { + if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now)) || (isInitialLocation)) { this.lastParkActionState = LastParkActionState.CARTRIP; - isinitialLocation = false; + isInitialLocation = false; // Leg currentLeg = (Leg) this.currentPlanElement; int planIndexNextActivity = planIndex + 1; Activity nextPlanElement = (Activity) plan.getPlanElements().get(planIndexNextActivity); - if (nextPlanElement.getAttributes().getAsMap().containsKey("parking") && nextPlanElement.getAttributes().getAttribute("parking").equals( - "noParking")) + if (ParkingUtils.checkIfActivityHasNoParking(nextPlanElement)) this.lastParkActionState = LastParkActionState.WALKFROMPARK; //this could be Car, Carsharing, Motorcylce, or whatever else mode we have, so we want our leg to reflect this. return new NearestParkingDynLeg(currentPlannedLeg, actualRoute, plan, planIndexNextActivity, parkingLogic, parkingManager, @@ -133,6 +119,22 @@ protected DynAction nextStateAfterActivity(DynAction oldAction, double now) { // we could either depart by car or not next if (plan.getPlanElements().size() >= planIndex + 1) { + if (plan.getPlanElements().get(planIndex) instanceof Activity && ((Activity) plan.getPlanElements().get(planIndex)).getType().equals( + ParkingUtils.WaitingForParkingActivityType)) { + //now the waiting activity has finished and we can park now + this.parkingManager.parkVehicleHere(Id.create(this.agent.getId(), Vehicle.class), agent.getCurrentLinkId(), now); + return nextStateAfterNonCarTrip(oldAction, now); + } + if (plan.getPlanElements().get(planIndex + 1) instanceof Activity) + return nextStateAfterNonCarTrip(oldAction, now); + if (plan.getPlanElements().get(planIndex) instanceof Activity && ((Activity) plan.getPlanElements().get(planIndex)).getType().contains("_GetOff")) { + ((Activity) plan.getPlanElements().get(planIndex)).setEndTime(now); + ((Activity) plan.getPlanElements().get(planIndex + 4)).setStartTime(now + ((Activity) plan.getPlanElements().get(planIndex + 2)).getMaximumDuration().seconds()); + // checks if it is possible to stay from getOff until getIn + boolean possibleToStay = checkIfParkingIsPossibleUntilNextActivities(this.planIndex,this.planIndex + 2); + if (possibleToStay) + return nextStateAfterNonCarTrip(oldAction, now); + } planIndex++; this.currentPlanElement = plan.getPlanElements().get(planIndex); Leg currentLeg = (Leg) currentPlanElement; @@ -141,7 +143,7 @@ protected DynAction nextStateAfterActivity(DynAction oldAction, double now) { Id parkLink = this.parkingManager.getVehicleParkingLocation(vehicleId); if (parkLink == null) { - //this is the first activity of a day and our parking manager does not provide informations about initial stages. We suppose the car is parked where we are + //this is the first activity of a day and our parking manager does not provide information about initial stages. We suppose the car is parked where we are parkLink = agent.getCurrentLinkId(); } @@ -151,14 +153,13 @@ protected DynAction nextStateAfterActivity(DynAction oldAction, double now) { Facility toFacility = new LinkWrapperFacility(network.getLinks().get(teleportedParkLink)); List walkTrip = walkRouter.calcRoute( DefaultRoutingRequest.withoutAttributes(fromFacility, toFacility, now, plan.getPerson())); - if (walkTrip.size() != 1 || !(walkTrip.get(0) instanceof Leg)) { + if (walkTrip.size() != 1 || !(walkTrip.get(0) instanceof Leg walkLeg)) { String message = "walkRouter returned something else than a single Leg, e.g. it routes walk on the network with non_network_walk to access the network. Not implemented in parking yet!"; log.error(message); throw new RuntimeException(message); } - Leg walkLeg = (Leg) walkTrip.get(0); this.currentlyAssignedVehicleId = vehicleId; - this.stageInteractionType = ParkingUtils.PARKACTIVITYTYPE; + this.stageInteractionType = ParkingUtils.ParkingStageInteractionType; if (!walkLeg.getTravelTime().equals(OptionalTime.defined(0.))) { this.lastParkActionState = LastParkActionState.WALKTOPARK; return new StaticPassengerDynLeg(walkLeg.getRoute(), walkLeg.getMode()); @@ -188,10 +189,96 @@ protected DynAction nextStateAfterActivity(DynAction oldAction, double now) { protected DynAction nextStateAfterWalkToPark(DynAction oldAction, double now) { //walk2park is complete, we can unpark. this.lastParkActionState = LastParkActionState.UNPARKACTIVITY; - PlanElement beforePlanElement = plan.getPlanElements().get(planIndex - 1); - if (beforePlanElement.getAttributes().getAsMap().containsKey("parking") && beforePlanElement.getAttributes().getAttribute("parking").equals( - "noParking")) - return nextStateAfterUnParkActivity(oldAction, now); + Activity beforePlanElement = (Activity) plan.getPlanElements().get(planIndex - 1); + if (ParkingUtils.checkIfActivityHasNoParking(beforePlanElement)) + return nextStateAfterUnParkActivity(oldAction, now); // wenn kein Parken dann einfach weiter return new IdleDynActivity(this.stageInteractionType, now + configGroup.getUnparkduration()); } + + @Override + protected DynAction nextStateAfterCarTrip(DynAction oldAction, double now) { + if (this.plan.getPlanElements().get(planIndex + 1) instanceof Activity && ((Activity) this.plan.getPlanElements().get( + planIndex + 1)).getType().equals(ParkingUtils.WaitingForParkingActivityType)) { + //next activity is waiting for parking. Thats why we have no parkVehicleHere at this moment + this.lastParkActionState = LastParkActionState.PARKACTIVITY; + this.currentlyAssignedVehicleId = null; + this.parkingLogic.reset(); + return new IdleDynActivity(this.stageInteractionType, now + configGroup.getParkduration()); + } + // car trip is complete, we have found a parking space (not part of the logic), block it and start to park + if (this.parkingManager.parkVehicleHere(Id.create(this.agent.getId(), Vehicle.class), agent.getCurrentLinkId(), now)) { + this.lastParkActionState = LastParkActionState.PARKACTIVITY; + this.currentlyAssignedVehicleId = null; + this.parkingLogic.reset(); + return new IdleDynActivity(this.stageInteractionType, now + configGroup.getParkduration()); + } else throw new RuntimeException("No parking possible"); + } + + @Override + protected DynAction nextStateAfterNonCarTrip(DynAction oldAction, double now) { + + this.currentPlanElement = plan.getPlanElements().get(planIndex + 1); + Activity nextPlannedActivity = (Activity) this.currentPlanElement; + // checks if you can extend parking here until getIn + if (nextPlannedActivity.getType().equals(ParkingUtils.ParkingActivityType) && plan.getPlanElements().get(planIndex + 2) instanceof Leg) { + checkIfParkingIsPossibleUntilNextActivities(planIndex + 1,planIndex + 1); + } + // switch back to activity + planIndex++; + this.lastParkActionState = LastParkActionState.ACTIVITY; + final double endTime; + if (nextPlannedActivity.getEndTime().isUndefined()) { + if (nextPlannedActivity.getMaximumDuration().isUndefined()) { + endTime = Double.POSITIVE_INFINITY; + //last activity of a day + } else { + endTime = now + nextPlannedActivity.getMaximumDuration().seconds(); + } + } else { + endTime = nextPlannedActivity.getEndTime().seconds(); + } + return new IdleDynActivity(nextPlannedActivity.getType(), endTime); + + } + + private boolean checkIfParkingIsPossibleUntilNextActivities(int indexOfCurrentActivity, int indexOfParkingActivity) { + int indexOfFollowingActivity = indexOfCurrentActivity + 2; + Activity followingActivity = ((Activity) plan.getPlanElements().get(indexOfFollowingActivity)); + //checks if it is possible to stay from the current getOff until the getIn + if (indexOfFollowingActivity == indexOfParkingActivity) { + Activity currentActivity = ((Activity) plan.getPlanElements().get(this.planIndex)); + Activity activityAfterFollowing = ((Activity) plan.getPlanElements().get(this.planIndex + 4)); + if (agent.getCurrentLinkId().equals(activityAfterFollowing.getLinkId()) && !ParkingUtils.checkIfActivityHasNoParking( + (Activity) currentPlanElement)) { + boolean canParkAtFacilityUntilGetIn = ((FacilityBasedParkingManager) parkingManager).canParkAtThisFacilityUntilEnd( + agent.getCurrentLinkId(), + followingActivity.getMaximumDuration().seconds(), currentActivity.getMaximumDuration().seconds(), + activityAfterFollowing.getMaximumDuration().seconds(), timer.getTimeOfDay()); + if (canParkAtFacilityUntilGetIn) { + plan.getPlanElements().remove(this.planIndex + 3); + plan.getPlanElements().remove(this.planIndex + 1); + ((FacilityBasedParkingManager) parkingManager).registerStayFromGetOffUntilGetIn(this.agent.getVehicle().getId()); + return true; + } + } + } + // checks if the now started parking activity can extend until the end of the following GetIn activity + else if (indexOfCurrentActivity == indexOfParkingActivity) { + Activity currentActivity = ((Activity) plan.getPlanElements().get(this.planIndex + 1)); + if (agent.getCurrentLinkId().equals(followingActivity.getLinkId()) && !ParkingUtils.checkIfActivityHasNoParking( + followingActivity)) { + boolean canParkAtFacilityUntilGetIn = ((FacilityBasedParkingManager) parkingManager).canParkAtThisFacilityUntilEnd( + agent.getCurrentLinkId(), + currentActivity.getMaximumDuration().seconds(), 0., + followingActivity.getMaximumDuration().seconds(), timer.getTimeOfDay()); + if (canParkAtFacilityUntilGetIn) { + plan.getPlanElements().remove(indexOfParkingActivity + 1); + currentActivity.setEndTime(followingActivity.getStartTime().seconds()); + ((FacilityBasedParkingManager) parkingManager).registerParkingBeforeGetIn(this.agent.getVehicle().getId()); + return true; + } + } + } + return false; + } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/ParkingAgentLogic.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/ParkingAgentLogic.java index 2bda5aa8698..dd2fb4fa74b 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/ParkingAgentLogic.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/DynAgent/agentLogic/ParkingAgentLogic.java @@ -59,25 +59,25 @@ /** * @author jbischoff - * */ public class ParkingAgentLogic implements DynAgentLogic { - public enum LastParkActionState { + public enum LastParkActionState { - // we have the following cases of ending dynacts: - NONCARTRIP, // non-car trip arrival: start Activity - CARTRIP, // car-trip arrival: add park-car activity - PARKACTIVITY, // park-car activity: get next PlanElement & add walk leg to activity location - WALKFROMPARK ,// walk-leg to act: start next PlanElement Activity - ACTIVITY, // ordinary activity: get next Leg, if car: go to car, otherwise add ordinary leg by other mode - WALKTOPARK, // walk-leg to car: add unpark activity - UNPARKACTIVITY // unpark activity: find the way to the next route & start leg + // we have the following cases of ending dynacts: + NONCARTRIP, // non-car trip arrival: start Activity + CARTRIP, // car-trip arrival: add park-car activity + PARKACTIVITY, // park-car activity: get next PlanElement & add walk leg to activity location + WALKFROMPARK,// walk-leg to act: start next PlanElement Activity + ACTIVITY, // ordinary activity: get next Leg, if car: go to car, otherwise add ordinary leg by other mode + WALKTOPARK, // walk-leg to car: add unpark activity + UNPARKACTIVITY // unpark activity: find the way to the next route & start leg } + protected LastParkActionState lastParkActionState; protected DynAgent agent; protected int planIndex; -// protected Iterator planElemIter; + // protected Iterator planElemIter; protected Plan plan; protected PlanElement currentPlanElement; protected ParkingSearchManager parkingManager; @@ -88,20 +88,18 @@ public enum LastParkActionState { protected EventsManager events; protected ParkingSearchLogic parkingLogic; protected VehicleTeleportationLogic teleportationLogic; - protected boolean isinitialLocation = true; + protected boolean isInitialLocation = true; protected Id currentlyAssignedVehicleId = null; protected String stageInteractionType = null; protected ParkingSearchConfigGroup configGroup; protected static final Logger log = LogManager.getLogger(ParkingAgentLogic.class); /** - * @param plan - * (always starts with Activity) + * @param plan (always starts with Activity) */ - public ParkingAgentLogic(Plan plan, ParkingSearchManager parkingManager, RoutingModule walkRouter, Network network, - ParkingRouter parkingRouter, EventsManager events, ParkingSearchLogic parkingLogic, MobsimTimer timer, - VehicleTeleportationLogic teleportationLogic, ParkingSearchConfigGroup configGroup) { -// planElemIter = plan.getPlanElements().iterator(); + public ParkingAgentLogic(Plan plan, ParkingSearchManager parkingManager, RoutingModule walkRouter, Network network, + ParkingRouter parkingRouter, EventsManager events, ParkingSearchLogic parkingLogic, MobsimTimer timer, + VehicleTeleportationLogic teleportationLogic, ParkingSearchConfigGroup configGroup) { this.plan = plan; this.parkingManager = parkingManager; this.walkRouter = walkRouter; @@ -141,32 +139,17 @@ public DynAction computeNextAction(DynAction oldAction, double now) { // ordinary activity: get next Leg, if car: go to car, otherwise add ordinary leg by other mode // walk-leg to car: add unpark activity // unpark activity: find the way to the next route & start leg - switch (lastParkActionState){ - case ACTIVITY: - return nextStateAfterActivity(oldAction, now); - - case CARTRIP: - return nextStateAfterCarTrip(oldAction,now); - - case NONCARTRIP: - return nextStateAfterNonCarTrip(oldAction,now); - - case PARKACTIVITY: - return nextStateAfterParkActivity(oldAction,now); - - case UNPARKACTIVITY: - return nextStateAfterUnParkActivity(oldAction,now); - - case WALKFROMPARK: - return nextStateAfterWalkFromPark(oldAction,now); - - case WALKTOPARK: - return nextStateAfterWalkToPark(oldAction,now); - - } - throw new RuntimeException("unreachable code"); - - } + return switch (lastParkActionState) { + case ACTIVITY -> nextStateAfterActivity(oldAction, now); + case CARTRIP -> nextStateAfterCarTrip(oldAction, now); + case NONCARTRIP -> nextStateAfterNonCarTrip(oldAction, now); + case PARKACTIVITY -> nextStateAfterParkActivity(oldAction, now); + case UNPARKACTIVITY -> nextStateAfterUnParkActivity(oldAction, now); + case WALKFROMPARK -> nextStateAfterWalkFromPark(oldAction, now); + case WALKTOPARK -> nextStateAfterWalkToPark(oldAction, now); + }; + + } protected DynAction nextStateAfterUnParkActivity(DynAction oldAction, double now) { // we have unparked, now we need to get going by car again. @@ -174,15 +157,14 @@ protected DynAction nextStateAfterUnParkActivity(DynAction oldAction, double now Leg currentPlannedLeg = (Leg) currentPlanElement; Route plannedRoute = currentPlannedLeg.getRoute(); NetworkRoute actualRoute = this.parkingRouter.getRouteFromParkingToDestination(plannedRoute.getEndLinkId(), now, agent.getCurrentLinkId()); - if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now))||(isinitialLocation)){ + if ((this.parkingManager.unParkVehicleHere(currentlyAssignedVehicleId, agent.getCurrentLinkId(), now)) || (isInitialLocation)) { this.lastParkActionState = LastParkActionState.CARTRIP; - isinitialLocation = false; + isInitialLocation = false; Leg currentLeg = (Leg) this.currentPlanElement; //this could be Car, Carsharing, Motorcylce, or whatever else mode we have, so we want our leg to reflect this. return new ParkingDynLeg(currentLeg.getMode(), actualRoute, parkingLogic, parkingManager, currentlyAssignedVehicleId, timer, events); - } - else throw new RuntimeException("parking location mismatch"); + } else throw new RuntimeException("parking location mismatch"); } @@ -200,15 +182,15 @@ protected DynAction nextStateAfterWalkFromPark(DynAction oldAction, double now) protected DynAction nextStateAfterParkActivity(DynAction oldAction, double now) { // add a walk leg after parking Leg currentPlannedLeg = (Leg) currentPlanElement; - Facility fromFacility = new LinkWrapperFacility (network.getLinks().get(agent.getCurrentLinkId())); - Facility toFacility = new LinkWrapperFacility (network.getLinks().get(currentPlannedLeg.getRoute().getEndLinkId())); - List walkTrip = walkRouter.calcRoute(DefaultRoutingRequest.withoutAttributes(fromFacility, toFacility, now, plan.getPerson())); - if (walkTrip.size() != 1 || ! (walkTrip.get(0) instanceof Leg)) { + Facility fromFacility = new LinkWrapperFacility(network.getLinks().get(agent.getCurrentLinkId())); + Facility toFacility = new LinkWrapperFacility(network.getLinks().get(currentPlannedLeg.getRoute().getEndLinkId())); + List walkTrip = walkRouter.calcRoute( + DefaultRoutingRequest.withoutAttributes(fromFacility, toFacility, now, plan.getPerson())); + if (walkTrip.size() != 1 || !(walkTrip.get(0) instanceof Leg walkLeg)) { String message = "walkRouter returned something else than a single Leg, e.g. it routes walk on the network with non_network_walk to access the network. Not implemented in parking yet!"; log.error(message); throw new RuntimeException(message); } - Leg walkLeg = (Leg) walkTrip.get(0); this.lastParkActionState = LastParkActionState.WALKFROMPARK; this.stageInteractionType = null; return new StaticPassengerDynLeg(walkLeg.getRoute(), walkLeg.getMode()); @@ -223,11 +205,11 @@ protected DynAction nextStateAfterNonCarTrip(DynAction oldAction, double now) { final double endTime; if (nextPlannedActivity.getEndTime().isUndefined()) { if (nextPlannedActivity.getMaximumDuration().isUndefined()) { - endTime = Double.POSITIVE_INFINITY; - //last activity of a day - } else { + endTime = Double.POSITIVE_INFINITY; + //last activity of a day + } else { endTime = now + nextPlannedActivity.getMaximumDuration().seconds(); - } + } } else { endTime = nextPlannedActivity.getEndTime().seconds(); } @@ -237,13 +219,12 @@ protected DynAction nextStateAfterNonCarTrip(DynAction oldAction, double now) { protected DynAction nextStateAfterCarTrip(DynAction oldAction, double now) { // car trip is complete, we have found a parking space (not part of the logic), block it and start to park - if (this.parkingManager.parkVehicleHere(Id.create(this.agent.getId(), Vehicle.class), agent.getCurrentLinkId(), now)){ - this.lastParkActionState = LastParkActionState.PARKACTIVITY; - this.currentlyAssignedVehicleId = null; - this.parkingLogic.reset(); + if (this.parkingManager.parkVehicleHere(Id.create(this.agent.getId(), Vehicle.class), agent.getCurrentLinkId(), now)) { + this.lastParkActionState = LastParkActionState.PARKACTIVITY; + this.currentlyAssignedVehicleId = null; + this.parkingLogic.reset(); return new IdleDynActivity(this.stageInteractionType, now + configGroup.getParkduration()); - } - else throw new RuntimeException ("No parking possible"); + } else throw new RuntimeException("No parking possible"); } protected DynAction nextStateAfterActivity(DynAction oldAction, double now) { @@ -263,19 +244,18 @@ protected DynAction nextStateAfterActivity(DynAction oldAction, double now) { Facility fromFacility = new LinkWrapperFacility(network.getLinks().get(agent.getCurrentLinkId())); Id teleportedParkLink = this.teleportationLogic.getVehicleLocation(agent.getCurrentLinkId(), vehicleId, parkLink, now, - currentLeg.getMode()); + currentLeg.getMode()); Facility toFacility = new LinkWrapperFacility(network.getLinks().get(teleportedParkLink)); List walkTrip = walkRouter.calcRoute( - DefaultRoutingRequest.withoutAttributes(fromFacility, toFacility, now, plan.getPerson())); - if (walkTrip.size() != 1 || !(walkTrip.get(0) instanceof Leg)) { + DefaultRoutingRequest.withoutAttributes(fromFacility, toFacility, now, plan.getPerson())); + if (walkTrip.size() != 1 || !(walkTrip.get(0) instanceof Leg walkLeg)) { String message = "walkRouter returned something else than a single Leg, e.g. it routes walk on the network with non_network_walk to access the network. Not implemented in parking yet!"; log.error(message); throw new RuntimeException(message); } - Leg walkLeg = (Leg) walkTrip.get(0); this.lastParkActionState = LastParkActionState.WALKTOPARK; this.currentlyAssignedVehicleId = vehicleId; - this.stageInteractionType = ParkingUtils.PARKACTIVITYTYPE; + this.stageInteractionType = ParkingUtils.ParkingStageInteractionType; return new StaticPassengerDynLeg(walkLeg.getRoute(), walkLeg.getMode()); } else if (currentLeg.getMode().equals(TransportMode.pt)) { if (currentLeg.getRoute() instanceof TransitPassengerRoute) { @@ -292,8 +272,8 @@ protected DynAction nextStateAfterActivity(DynAction oldAction, double now) { } } else throw new RuntimeException( - "no more leg to follow but activity is ending\nLastPlanElement: " + currentPlanElement.toString() + "\n Agent " + this.agent.getId() + "\nTime: " + Time.writeTime( - now)); + "no more leg to follow but activity is ending\nLastPlanElement: " + currentPlanElement.toString() + "\n Agent " + this.agent.getId() + "\nTime: " + Time.writeTime( + now)); } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/ParkingUtils.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/ParkingUtils.java index fc5abd290c6..c3f2a38eb87 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/ParkingUtils.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/ParkingUtils.java @@ -21,18 +21,21 @@ import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.population.Activity; import java.util.ArrayList; import java.util.List; import java.util.Random; /** - * @author jbischoff, tschlenther + * @author jbischoff, tschlenther, Ricardo Ewert * */ public class ParkingUtils { - static public final String PARKACTIVITYTYPE = "parking"; + static public final String ParkingStageInteractionType = "parking"; + static public final String ParkingActivityType = "parking_activity"; + static public final String WaitingForParkingActivityType = "waitingForParkingSpace_activity"; static public final int NO_OF_LINKS_TO_GET_ON_ROUTE = 5; @@ -143,4 +146,45 @@ public static List getOutgoingLinksForMode(Link link, String mode) { return outGoingModeLinks; } + /** + * Checks if the activity has parking while the activity. + * + * @param followingActivity + * @return + */ + public static boolean checkIfActivityHasNoParking(Activity followingActivity) { + return followingActivity.getAttributes().getAsMap().containsKey("parking") && followingActivity.getAttributes().getAttribute( + "parking").equals("noParking"); + + } + + /** + * Sets that while this activity we simulate no parking activities. + * + * @param activity + */ + public static void setNoParkingForActivity(Activity activity) { + activity.getAttributes().putAttribute("parking", "noParking"); + } + + /** + * This activity has a passenger interaction. This would mean that the location is fixed, and can not be changed. + * + * @param activity + */ + public static void setPassangerInteractionForActivity(Activity activity) { + activity.getAttributes().putAttribute("parking", "PassangerInteraction"); + } + + /** + * Checks if the activity has a passanger interaction. This would mean that the location is fixed, and can not be changed. + * + * @param activity + * @return + */ + public static boolean checkIfActivityHasPassengerInteraction(Activity activity) { + return activity.getAttributes().getAsMap().containsKey("parking") && activity.getAttributes().getAttribute( + "parking").equals( + "PassangerInteraction"); + } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingListener.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingListener.java index 9203fe45526..41e370c8065 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingListener.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingListener.java @@ -26,9 +26,13 @@ import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.controler.events.IterationEndsEvent; import org.matsim.core.controler.listener.IterationEndsListener; +import org.matsim.core.mobsim.framework.events.MobsimBeforeSimStepEvent; +import org.matsim.core.mobsim.framework.events.MobsimInitializedEvent; +import org.matsim.core.mobsim.framework.listeners.MobsimBeforeSimStepListener; +import org.matsim.core.mobsim.framework.listeners.MobsimInitializedListener; +import org.matsim.core.mobsim.qsim.QSim; import org.matsim.core.utils.io.IOUtils; - import java.io.BufferedWriter; import java.io.IOException; import java.util.List; @@ -38,7 +42,7 @@ * */ -public class ParkingListener implements IterationEndsListener { +public class ParkingListener implements IterationEndsListener, MobsimBeforeSimStepListener, MobsimInitializedListener { @Inject ParkingSearchManager manager; @@ -59,7 +63,7 @@ private void writeStatsByTimesteps(List produceBeneStatistics, int itera BufferedWriter bw = IOUtils.getBufferedWriter(output.getIterationFilename(iteration, "parkingStatsPerTimeSteps.csv")); try { - String header = "time;rejectedReservations;foundParking;unpark"; + String header = "time;rejectedParkingRequest;foundParking;unpark"; bw.write(header); bw.newLine(); for (String s : produceBeneStatistics){ @@ -82,7 +86,7 @@ private void writeStats(List produceStatistics, int iteration) { BufferedWriter bw = IOUtils.getBufferedWriter(output.getIterationFilename(iteration, "parkingStats.csv")); try { - String header = "linkId;X;Y;parkingFacility;capacity;EndOccupation;reservationsRequests;numberOfParkedVehicles;rejectedReservations"; + String header = "linkId;X;Y;parkingFacility;capacity;EndOccupation;reservationsRequests;numberOfParkedVehicles;rejectedParkingRequest;numberOfWaitingActivities;numberOfStaysFromGetOffUntilGetIn;numberOfParkingBeforeGetIn"; bw.write(header); bw.newLine(); for (String s : produceStatistics){ @@ -99,4 +103,15 @@ private void writeStats(List produceStatistics, int iteration) { } + @Override + public void notifyMobsimBeforeSimStep(MobsimBeforeSimStepEvent event) { + ((FacilityBasedParkingManager) manager).checkFreeCapacitiesForWaitingVehicles((QSim) event.getQueueSimulation(), event.getSimulationTime()); + } + + @Override + public void notifyMobsimInitialized(final MobsimInitializedEvent e) { + QSim qSim = (QSim) e.getQueueSimulation(); + ((FacilityBasedParkingManager) manager).setQSim(qSim); + + } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingSlotVisualiser.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingSlotVisualiser.java index e475acbb181..50587d72059 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingSlotVisualiser.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/evaluation/ParkingSlotVisualiser.java @@ -1,202 +1,202 @@ -/* *********************************************************************** * - * project: org.matsim.* - * *********************************************************************** * - * * - * copyright : (C) ${year} by the members listed in the COPYING, * - * LICENSE and WARRANTY file. * - * email : info at matsim dot org * - * * - * *********************************************************************** * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * See also COPYING, LICENSE and WARRANTY file * - * * - * *********************************************************************** */ - -package org.matsim.contrib.parking.parkingsearch.evaluation; - -import com.google.inject.Inject; -import org.apache.commons.lang3.mutable.MutableDouble; -import org.apache.logging.log4j.LogManager; -import org.matsim.api.core.v01.Coord; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.Scenario; -import org.matsim.api.core.v01.events.PersonEntersVehicleEvent; -import org.matsim.api.core.v01.events.PersonLeavesVehicleEvent; -import org.matsim.api.core.v01.events.VehicleEntersTrafficEvent; -import org.matsim.api.core.v01.events.VehicleLeavesTrafficEvent; -import org.matsim.api.core.v01.events.handler.PersonEntersVehicleEventHandler; -import org.matsim.api.core.v01.events.handler.PersonLeavesVehicleEventHandler; -import org.matsim.api.core.v01.events.handler.VehicleEntersTrafficEventHandler; -import org.matsim.api.core.v01.events.handler.VehicleLeavesTrafficEventHandler; -import org.matsim.api.core.v01.network.Link; -import org.matsim.api.core.v01.network.Network; -import org.matsim.contrib.parking.parkingsearch.ParkingUtils; -import org.matsim.core.controler.events.IterationEndsEvent; -import org.matsim.core.controler.listener.IterationEndsListener; -import org.matsim.core.gbl.MatsimRandom; -import org.matsim.core.utils.collections.Tuple; -import org.matsim.core.utils.io.IOUtils; -import org.matsim.facilities.ActivityFacility; -import org.matsim.vehicles.Vehicle; - -import java.io.BufferedWriter; -import java.io.IOException; -import java.util.*; -import java.util.Map.Entry; - -public class ParkingSlotVisualiser implements PersonEntersVehicleEventHandler, PersonLeavesVehicleEventHandler, VehicleLeavesTrafficEventHandler, VehicleEntersTrafficEventHandler, IterationEndsListener { - - Network network; - - protected Map, ParkingSlotManager> slotsOnLink = new HashMap, ParkingSlotManager>(); - protected Map, Double> midnightParkers = new HashMap, Double>(); - protected Map, ParkingSlotManager> vehiclesResponsibleManager = new HashMap<>(); - Random r = MatsimRandom.getLocalInstance(); - protected List parkings = new ArrayList<>(); - - Map, Id> parkedVehicles = new HashMap, Id>(); - - /** - * - */ - @Inject - public ParkingSlotVisualiser(Scenario scenario) { - this.network = scenario.getNetwork(); - Map, ActivityFacility> parkingFacilities = scenario.getActivityFacilities().getFacilitiesForActivityType( - ParkingUtils.PARKACTIVITYTYPE); - initialize(parkingFacilities); - } - - public ParkingSlotVisualiser(Network network, Map, ActivityFacility> parkingFacilities) { - this.network = network; - initialize(parkingFacilities); - } - - private void initialize(Map, ActivityFacility> parkingFacilities) { - Map, MutableDouble> nrOfSlotsPerLink = new HashMap, MutableDouble>(); - for (ActivityFacility fac : parkingFacilities.values()) { - Id linkId = fac.getLinkId(); - if (nrOfSlotsPerLink.containsKey(linkId)) { - nrOfSlotsPerLink.get(linkId).add(fac.getActivityOptions().get(ParkingUtils.PARKACTIVITYTYPE).getCapacity()); - } else { - nrOfSlotsPerLink.put(linkId, new MutableDouble(fac.getActivityOptions().get(ParkingUtils.PARKACTIVITYTYPE).getCapacity())); - } - } - - for (Id linkID : nrOfSlotsPerLink.keySet()) { -// LogManager.getLogger(getClass()).info("initialize parking visualisation for link " + linkID); - this.slotsOnLink.put(linkID, new ParkingSlotManager(network.getLinks().get(linkID), nrOfSlotsPerLink.get(linkID).intValue())); - } - } - - - @Override - public void reset(int iteration) { - for (Id link : this.slotsOnLink.keySet()) { - this.slotsOnLink.get(link).setAllParkingTimesToZero(); - } - } - - @Override - public void handleEvent(VehicleLeavesTrafficEvent event) { - if (this.slotsOnLink.containsKey(event.getLinkId())) { - this.vehiclesResponsibleManager.put(event.getVehicleId(), this.slotsOnLink.get(event.getLinkId())); - } - } - - @Override - public void handleEvent(PersonLeavesVehicleEvent event) { - ParkingSlotManager manager = this.vehiclesResponsibleManager.remove(event.getVehicleId()); - if (manager != null) { - Tuple parkingTuple = manager.processParking(event.getTime(), event.getVehicleId()); - this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + event.getTime() + ";" + - parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "free"); - this.parkedVehicles.put(event.getVehicleId(), manager.getLinkId()); - } - } - - - @Override - public void handleEvent(PersonEntersVehicleEvent event) { - if (this.parkedVehicles.containsKey(event.getVehicleId())) { - ParkingSlotManager manager = this.slotsOnLink.get(this.parkedVehicles.get(event.getVehicleId())); - Tuple parkingTuple = manager.processUnParking(event.getTime(), event.getVehicleId()); - this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + event.getTime() + ";" + - parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "veh" + event.getVehicleId()); - this.parkedVehicles.remove(event.getVehicleId()); - } else { - midnightParkers.put(event.getVehicleId(), event.getTime()); - } - } - - /* (non-Javadoc) - * @see org.matsim.api.core.v01.events.handler.VehicleEntersTrafficEventHandler#handleEvent(org.matsim.api.core.v01.events.VehicleEntersTrafficEvent) - */ - @Override - public void handleEvent(VehicleEntersTrafficEvent event) { - if (this.midnightParkers.containsKey(event.getVehicleId())) { - if (this.slotsOnLink.containsKey(event.getLinkId())) { - ParkingSlotManager manager = this.slotsOnLink.get(event.getLinkId()); - Tuple parkingTuple = manager.processUnParking(event.getTime(), event.getVehicleId()); - if (parkingTuple != null) { - this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + event.getTime() + ";" + - parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "veh" + event.getVehicleId()); - } - } - this.midnightParkers.remove(event.getVehicleId()); - } - } - - public void finishDay() { - - for (Id linkId : this.slotsOnLink.keySet()) { - ParkingSlotManager manager = this.slotsOnLink.get(linkId); - Map, Tuple> occupiedSlots = manager.getOccupiedSlots(); - - double endOfDay = 30 * 3600; - for (Entry, Tuple> e : occupiedSlots.entrySet()) { - Tuple parkingTuple = e.getValue(); - this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + endOfDay + ";" + - parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "veh" + e.getKey()); - - // set back to 0 - } - - List> freeSlots = manager.getFreeSlots(); - for (Tuple parkingTuple : freeSlots) { - this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + endOfDay + ";" + - parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "free"); - } - } - } - - public void plotSlotOccupation(String filename) { - String head = "LinkId;from;To;X;Y;OccupiedByVehicle"; - BufferedWriter bw = IOUtils.getBufferedWriter(filename); - try { - bw.write(head); - for (String s : this.parkings) { - bw.newLine(); - bw.write(s); - } - bw.flush(); - bw.close(); - } catch (IOException e) { - e.printStackTrace(); - } - LogManager.getLogger(getClass()).info("FINISHED WRITING PARKING SLOT VISUALISATION FILE TO: " + filename); - } - - @Override - public void notifyIterationEnds(IterationEndsEvent event) { - String path = event.getServices().getControlerIO().getIterationFilename(event.getIteration(), - "ParkingSlots_it" + event.getIteration() + ".csv"); - this.finishDay(); - this.plotSlotOccupation(path); - } -} - +/* *********************************************************************** * + * project: org.matsim.* + * *********************************************************************** * + * * + * copyright : (C) ${year} by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +package org.matsim.contrib.parking.parkingsearch.evaluation; + +import com.google.inject.Inject; +import org.apache.commons.lang3.mutable.MutableDouble; +import org.apache.logging.log4j.LogManager; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.events.PersonEntersVehicleEvent; +import org.matsim.api.core.v01.events.PersonLeavesVehicleEvent; +import org.matsim.api.core.v01.events.VehicleEntersTrafficEvent; +import org.matsim.api.core.v01.events.VehicleLeavesTrafficEvent; +import org.matsim.api.core.v01.events.handler.PersonEntersVehicleEventHandler; +import org.matsim.api.core.v01.events.handler.PersonLeavesVehicleEventHandler; +import org.matsim.api.core.v01.events.handler.VehicleEntersTrafficEventHandler; +import org.matsim.api.core.v01.events.handler.VehicleLeavesTrafficEventHandler; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.parking.parkingsearch.ParkingUtils; +import org.matsim.core.controler.events.IterationEndsEvent; +import org.matsim.core.controler.listener.IterationEndsListener; +import org.matsim.core.gbl.MatsimRandom; +import org.matsim.core.utils.collections.Tuple; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.facilities.ActivityFacility; +import org.matsim.vehicles.Vehicle; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.util.*; +import java.util.Map.Entry; + +public class ParkingSlotVisualiser implements PersonEntersVehicleEventHandler, PersonLeavesVehicleEventHandler, VehicleLeavesTrafficEventHandler, VehicleEntersTrafficEventHandler, IterationEndsListener { + + Network network; + + protected Map, ParkingSlotManager> slotsOnLink = new HashMap, ParkingSlotManager>(); + protected Map, Double> midnightParkers = new HashMap, Double>(); + protected Map, ParkingSlotManager> vehiclesResponsibleManager = new HashMap<>(); + Random r = MatsimRandom.getLocalInstance(); + protected List parkings = new ArrayList<>(); + + protected Map, Id> parkedVehicles = new HashMap, Id>(); + + /** + * + */ + @Inject + public ParkingSlotVisualiser(Scenario scenario) { + this.network = scenario.getNetwork(); + Map, ActivityFacility> parkingFacilities = scenario.getActivityFacilities().getFacilitiesForActivityType( + ParkingUtils.ParkingStageInteractionType); + initialize(parkingFacilities); + } + + public ParkingSlotVisualiser(Network network, Map, ActivityFacility> parkingFacilities) { + this.network = network; + initialize(parkingFacilities); + } + + private void initialize(Map, ActivityFacility> parkingFacilities) { + Map, MutableDouble> nrOfSlotsPerLink = new HashMap, MutableDouble>(); + for (ActivityFacility fac : parkingFacilities.values()) { + Id linkId = fac.getLinkId(); + if (nrOfSlotsPerLink.containsKey(linkId)) { + nrOfSlotsPerLink.get(linkId).add(fac.getActivityOptions().get(ParkingUtils.ParkingStageInteractionType).getCapacity()); + } else { + nrOfSlotsPerLink.put(linkId, new MutableDouble(fac.getActivityOptions().get(ParkingUtils.ParkingStageInteractionType).getCapacity())); + } + } + + for (Id linkID : nrOfSlotsPerLink.keySet()) { +// LogManager.getLogger(getClass()).info("initialize parking visualisation for link " + linkID); + this.slotsOnLink.put(linkID, new ParkingSlotManager(network.getLinks().get(linkID), nrOfSlotsPerLink.get(linkID).intValue())); + } + } + + + @Override + public void reset(int iteration) { + for (Id link : this.slotsOnLink.keySet()) { + this.slotsOnLink.get(link).setAllParkingTimesToZero(); + } + } + + @Override + public void handleEvent(VehicleLeavesTrafficEvent event) { + if (this.slotsOnLink.containsKey(event.getLinkId())) { + this.vehiclesResponsibleManager.put(event.getVehicleId(), this.slotsOnLink.get(event.getLinkId())); + } + } + + @Override + public void handleEvent(PersonLeavesVehicleEvent event) { + ParkingSlotManager manager = this.vehiclesResponsibleManager.remove(event.getVehicleId()); + if (manager != null) { + Tuple parkingTuple = manager.processParking(event.getTime(), event.getVehicleId()); + this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + event.getTime() + ";" + + parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "free"); + this.parkedVehicles.put(event.getVehicleId(), manager.getLinkId()); + } + } + + + @Override + public void handleEvent(PersonEntersVehicleEvent event) { + if (this.parkedVehicles.containsKey(event.getVehicleId())) { + ParkingSlotManager manager = this.slotsOnLink.get(this.parkedVehicles.get(event.getVehicleId())); + Tuple parkingTuple = manager.processUnParking(event.getTime(), event.getVehicleId()); + this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + event.getTime() + ";" + + parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "veh" + event.getVehicleId()); + this.parkedVehicles.remove(event.getVehicleId()); + } else { + midnightParkers.put(event.getVehicleId(), event.getTime()); + } + } + + /* (non-Javadoc) + * @see org.matsim.api.core.v01.events.handler.VehicleEntersTrafficEventHandler#handleEvent(org.matsim.api.core.v01.events.VehicleEntersTrafficEvent) + */ + @Override + public void handleEvent(VehicleEntersTrafficEvent event) { + if (this.midnightParkers.containsKey(event.getVehicleId())) { + if (this.slotsOnLink.containsKey(event.getLinkId())) { + ParkingSlotManager manager = this.slotsOnLink.get(event.getLinkId()); + Tuple parkingTuple = manager.processUnParking(event.getTime(), event.getVehicleId()); + if (parkingTuple != null) { + this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + event.getTime() + ";" + + parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "veh" + event.getVehicleId()); + } + } + this.midnightParkers.remove(event.getVehicleId()); + } + } + + public void finishDay() { + + for (Id linkId : this.slotsOnLink.keySet()) { + ParkingSlotManager manager = this.slotsOnLink.get(linkId); + Map, Tuple> occupiedSlots = manager.getOccupiedSlots(); + + double endOfDay = 30 * 3600; + for (Entry, Tuple> e : occupiedSlots.entrySet()) { + Tuple parkingTuple = e.getValue(); + this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + endOfDay + ";" + + parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "veh" + e.getKey()); + + // set back to 0 + } + + List> freeSlots = manager.getFreeSlots(); + for (Tuple parkingTuple : freeSlots) { + this.parkings.add(manager.getLinkId() + ";" + parkingTuple.getSecond() + ";" + endOfDay + ";" + + parkingTuple.getFirst().getX() + ";" + parkingTuple.getFirst().getY() + ";" + "free"); + } + } + } + + public void plotSlotOccupation(String filename) { + String head = "LinkId;from;To;X;Y;OccupiedByVehicle"; + BufferedWriter bw = IOUtils.getBufferedWriter(filename); + try { + bw.write(head); + for (String s : this.parkings) { + bw.newLine(); + bw.write(s); + } + bw.flush(); + bw.close(); + } catch (IOException e) { + e.printStackTrace(); + } + LogManager.getLogger(getClass()).info("FINISHED WRITING PARKING SLOT VISUALISATION FILE TO: " + filename); + } + + @Override + public void notifyIterationEnds(IterationEndsEvent event) { + String path = event.getServices().getControlerIO().getIterationFilename(event.getIteration(), + "ParkingSlots_it" + event.getIteration() + ".csv"); + this.finishDay(); + this.plotSlotOccupation(path); + } +} + diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/events/StartWaitingForParkingEvent.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/events/StartWaitingForParkingEvent.java new file mode 100644 index 00000000000..992fd8763e6 --- /dev/null +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/events/StartWaitingForParkingEvent.java @@ -0,0 +1,68 @@ +/* *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2016 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +package org.matsim.contrib.parking.parkingsearch.events; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.events.Event; +import org.matsim.api.core.v01.network.Link; +import org.matsim.vehicles.Vehicle; + +import java.util.Map; + +/** + * @author jbischoff + */ + +public class StartWaitingForParkingEvent extends Event { + public static final String EVENT_TYPE = "started waiting for parking"; + public static final String ATTRIBUTE_VEHICLE = "vehicle"; + public static final String ATTRIBUTE_LINK = "link"; + private final Id linkId; + private final Id vehicleId; + + public StartWaitingForParkingEvent(final double time, Id vehicleId, Id linkId) { + super(time); + this.linkId = linkId; + this.vehicleId = vehicleId; + + } + + @Override + public String getEventType() { + return EVENT_TYPE; + } + + public Id getLinkId() { + return linkId; + } + + public Id getVehicleId() { + return vehicleId; + } + + @Override + public Map getAttributes() { + Map attr = super.getAttributes(); + attr.put(ATTRIBUTE_VEHICLE, this.vehicleId.toString()); + attr.put(ATTRIBUTE_LINK, this.linkId.toString()); + return attr; + } + +} diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleSpecifications.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/events/StartWaitingForParkingEventHandler.java similarity index 60% rename from contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleSpecifications.java rename to contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/events/StartWaitingForParkingEventHandler.java index 225d5be689d..24d5beb7d33 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/fleet/ElectricVehicleSpecifications.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/events/StartWaitingForParkingEventHandler.java @@ -1,9 +1,9 @@ -/* - * *********************************************************************** * +/* *********************************************************************** * * project: org.matsim.* + * * * *********************************************************************** * * * - * copyright : (C) 2022 by the members listed in the COPYING, * + * copyright : (C) 2016 by the members listed in the COPYING, * * LICENSE and WARRANTY file. * * email : info at matsim dot org * * * @@ -15,22 +15,18 @@ * (at your option) any later version. * * See also COPYING, LICENSE and WARRANTY file * * * - * *********************************************************************** * - */ + * *********************************************************************** */ + +package org.matsim.contrib.parking.parkingsearch.events; -package org.matsim.contrib.ev.fleet; +import org.matsim.core.events.handler.EventHandler; -import java.util.Collection; +/** + * @author jbischoff + */ -import org.matsim.vehicles.EngineInformation; -import org.matsim.vehicles.Vehicle; +public interface StartWaitingForParkingEventHandler extends EventHandler { -public class ElectricVehicleSpecifications { - public static void setInitialSoc(Vehicle vehicle, double initialSoc) { - vehicle.getAttributes().putAttribute(ElectricVehicleSpecificationImpl.INITIAL_SOC, initialSoc); - } + public void handleEvent(StartWaitingForParkingEvent event); - public static void setChargerTypes(EngineInformation engineInformation, Collection chargerTypes) { - engineInformation.getAttributes().putAttribute(ElectricVehicleSpecificationImpl.CHARGER_TYPES, chargerTypes); - } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/FacilityBasedParkingManager.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/FacilityBasedParkingManager.java index ce0cc3a9e4d..9b3b8eff107 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/FacilityBasedParkingManager.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/FacilityBasedParkingManager.java @@ -26,26 +26,32 @@ import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.dynagent.DynAgent; import org.matsim.contrib.parking.parkingsearch.ParkingUtils; import org.matsim.contrib.parking.parkingsearch.sim.ParkingSearchConfigGroup; +import org.matsim.core.mobsim.qsim.QSim; import org.matsim.core.utils.misc.Time; import org.matsim.facilities.ActivityFacility; +import org.matsim.facilities.ActivityOption; import org.matsim.vehicles.Vehicle; import java.util.*; import java.util.Map.Entry; /** - * @author jbischoff, schlenther - * + * @author jbischoff, schlenther, Ricardo Ewert */ public class FacilityBasedParkingManager implements ParkingSearchManager { protected Map, Integer> capacity = new HashMap<>(); protected Map, MutableLong> occupation = new HashMap<>(); protected Map, MutableLong> reservationsRequests = new HashMap<>(); - protected Map, MutableLong> rejectedReservations = new HashMap<>(); + protected Map, MutableLong> rejectedParkingRequest = new HashMap<>(); protected Map, MutableLong> numberOfParkedVehicles = new HashMap<>(); + protected Map, MutableLong> numberOfWaitingActivities = new HashMap<>(); + protected Map, MutableLong> numberOfStaysFromGetOffUntilGetIn = new HashMap<>(); + protected Map, MutableLong> numberOfParkingBeforeGetIn = new HashMap<>(); + protected Map, TreeMap>> waitingVehicles = new HashMap<>(); protected TreeMap rejectedReservationsByTime = new TreeMap<>(); protected TreeMap foundParkingByTime = new TreeMap<>(); protected TreeMap unparkByTime = new TreeMap<>(); @@ -54,8 +60,10 @@ public class FacilityBasedParkingManager implements ParkingSearchManager { protected Map, Id> parkingReservation = new HashMap<>(); protected Map, Id> parkingLocationsOutsideFacilities = new HashMap<>(); protected Map, Set>> facilitiesPerLink = new HashMap<>(); - protected Network network; + protected Network network; + protected ParkingSearchConfigGroup psConfigGroup; protected boolean canParkOnlyAtFacilities; + private QSim qsim; private final int maxSlotIndex; private final int maxTime; private final int timeBinSize; @@ -63,14 +71,15 @@ public class FacilityBasedParkingManager implements ParkingSearchManager { @Inject public FacilityBasedParkingManager(Scenario scenario) { - ParkingSearchConfigGroup psConfigGroup = (ParkingSearchConfigGroup) scenario.getConfig().getModules().get(ParkingSearchConfigGroup.GROUP_NAME); + psConfigGroup = (ParkingSearchConfigGroup) scenario.getConfig().getModules().get( + ParkingSearchConfigGroup.GROUP_NAME); canParkOnlyAtFacilities = psConfigGroup.getCanParkOnlyAtFacilities(); this.network = scenario.getNetwork(); parkingFacilities = scenario.getActivityFacilities() - .getFacilitiesForActivityType(ParkingUtils.PARKACTIVITYTYPE); + .getFacilitiesForActivityType(ParkingUtils.ParkingStageInteractionType); LogManager.getLogger(getClass()).info(parkingFacilities.toString()); - this.timeBinSize = 15*60; - this.maxTime = 24 * 3600 -1; + this.timeBinSize = 15 * 60; + this.maxTime = 24 * 3600 - 1; this.maxSlotIndex = (this.maxTime / this.timeBinSize) + 1; this.startTime = 9 * 3600; @@ -82,10 +91,14 @@ public FacilityBasedParkingManager(Scenario scenario) { } parkingOnLink.add(fac.getId()); this.facilitiesPerLink.put(linkId, parkingOnLink); + this.waitingVehicles.computeIfAbsent(linkId, (k) -> new TreeMap<>()); this.occupation.put(fac.getId(), new MutableLong(0)); this.reservationsRequests.put(fac.getId(), new MutableLong(0)); - this.rejectedReservations.put(fac.getId(), new MutableLong(0)); + this.rejectedParkingRequest.put(fac.getId(), new MutableLong(0)); this.numberOfParkedVehicles.put(fac.getId(), new MutableLong(0)); + this.numberOfWaitingActivities.put(fac.getId(), new MutableLong(0)); + this.numberOfStaysFromGetOffUntilGetIn.put(fac.getId(), new MutableLong(0)); + this.numberOfParkingBeforeGetIn.put(fac.getId(), new MutableLong(0)); } int slotIndex = getTimeSlotIndex(startTime); while (slotIndex <= maxSlotIndex) { @@ -109,6 +122,39 @@ public boolean reserveSpaceIfVehicleCanParkHere(Id vehicleId, Id return canPark; } + /** + * Checks if it is possible if you can park at this link for the complete time. + * + * @param linkId + * @param stopDuration + * @param getOffDuration + * @param pickUpDuration + * @param now + * @return + */ + public boolean canParkAtThisFacilityUntilEnd(Id linkId, double stopDuration, double getOffDuration, double pickUpDuration, double now) { + Set> facilities = this.facilitiesPerLink.get(linkId); + if (facilities != null) { + double totalNeededParkingDuration = getOffDuration + stopDuration + pickUpDuration; + for (Id facility : facilities) { + double maxParkingDurationAtFacilityInHours = Double.MAX_VALUE; + if (this.parkingFacilities.get(facility).getAttributes().getAsMap().containsKey("maxParkingDurationInHours")) + maxParkingDurationAtFacilityInHours = 3600 * (double) this.parkingFacilities.get(facility).getAttributes().getAsMap().get( + "maxParkingDurationInHours"); + if (maxParkingDurationAtFacilityInHours > totalNeededParkingDuration) { + ActivityOption parkingOptions = this.parkingFacilities.get(facility).getActivityOptions().get("parking"); + if (!parkingOptions.getOpeningTimes().isEmpty()) { + if ((parkingOptions.getOpeningTimes().first().getStartTime() == 0 && parkingOptions.getOpeningTimes().first().getEndTime() == 24 * 3600)) + if (parkingOptions.getOpeningTimes().first().getStartTime() <= now && parkingOptions.getOpeningTimes().first().getEndTime() >= now + totalNeededParkingDuration) + return true; + } else + return true; + } + } + } + return false; + } + private boolean linkIdHasAvailableParkingForVehicle(Id linkId, Id vid) { // LogManager.getLogger(getClass()).info("link "+linkId+" vehicle "+vid); if (!this.facilitiesPerLink.containsKey(linkId) && !canParkOnlyAtFacilities) { @@ -125,8 +171,8 @@ private boolean linkIdHasAvailableParkingForVehicle(Id linkId, Id } Set> parkingFacilitiesAtLink = this.facilitiesPerLink.get(linkId); for (Id fac : parkingFacilitiesAtLink) { - double cap = this.parkingFacilities.get(fac).getActivityOptions().get(ParkingUtils.PARKACTIVITYTYPE) - .getCapacity(); + double cap = this.parkingFacilities.get(fac).getActivityOptions().get(ParkingUtils.ParkingStageInteractionType) + .getCapacity(); this.reservationsRequests.get(fac).increment(); if (this.occupation.get(fac).doubleValue() < cap) { // LogManager.getLogger(getClass()).info("occ: @@ -136,7 +182,7 @@ private boolean linkIdHasAvailableParkingForVehicle(Id linkId, Id return true; } - this.rejectedReservations.get(fac).increment(); + this.rejectedParkingRequest.get(fac).increment(); } return false; } @@ -150,7 +196,7 @@ public Id getVehicleParkingLocation(Id vehicleId) { @Override public boolean parkVehicleHere(Id vehicleId, Id linkId, double time) { - return parkVehicleAtLink(vehicleId, linkId, time); + return parkVehicleAtLink(vehicleId, linkId, time); } protected boolean parkVehicleAtLink(Id vehicleId, Id linkId, double time) { @@ -167,7 +213,7 @@ protected boolean parkVehicleAtLink(Id vehicleId, Id linkId, doub return true; } else { throw new RuntimeException("no parking reservation found for vehicle " + vehicleId.toString() - + "arrival on link " + linkId + " with parking restriction"); + + " arrival on link " + linkId + " with parking restriction"); } } } @@ -193,11 +239,14 @@ public List produceStatistics() { for (Entry, MutableLong> e : this.occupation.entrySet()) { Id linkId = this.parkingFacilities.get(e.getKey()).getLinkId(); double capacity = this.parkingFacilities.get(e.getKey()).getActivityOptions() - .get(ParkingUtils.PARKACTIVITYTYPE).getCapacity(); + .get(ParkingUtils.ParkingStageInteractionType).getCapacity(); double x = this.parkingFacilities.get(e.getKey()).getCoord().getX(); double y = this.parkingFacilities.get(e.getKey()).getCoord().getY(); - String s = linkId.toString() + ";" + x + ";" + y + ";" + e.getKey().toString() + ";" + capacity + ";" + e.getValue().toString() + ";" + this.reservationsRequests.get(e.getKey()).toString() + ";" + this.numberOfParkedVehicles.get(e.getKey()).toString() + ";" + this.rejectedReservations.get(e.getKey()).toString(); + String s = linkId.toString() + ";" + x + ";" + y + ";" + e.getKey().toString() + ";" + capacity + ";" + e.getValue().toString() + ";" + this.reservationsRequests.get( + e.getKey()).toString() + ";" + this.numberOfParkedVehicles.get(e.getKey()).toString() + ";" + this.rejectedParkingRequest.get( + e.getKey()).toString() + ";" + this.numberOfWaitingActivities.get( + e.getKey()).toString() + ";" + this.numberOfStaysFromGetOffUntilGetIn.get(e.getKey()).intValue() + ";" + this.numberOfParkingBeforeGetIn.get(e.getKey()).intValue(); stats.add(s); } return stats; @@ -208,31 +257,32 @@ public List produceTimestepsStatistics() { for (int time : rejectedReservationsByTime.keySet()) { String s = Time.writeTime(time, Time.TIMEFORMAT_HHMM) + ";" + rejectedReservationsByTime.get(time) + ";" + foundParkingByTime.get( - time) + ";" + unparkByTime.get(time); + time) + ";" + unparkByTime.get(time); stats.add(s); } return stats; } - public double getNrOfAllParkingSpacesOnLink (Id linkId){ + + public double getNrOfAllParkingSpacesOnLink(Id linkId) { double allSpaces = 0; Set> parkingFacilitiesAtLink = this.facilitiesPerLink.get(linkId); if (!(parkingFacilitiesAtLink == null)) { - for (Id fac : parkingFacilitiesAtLink){ - allSpaces += this.parkingFacilities.get(fac).getActivityOptions().get(ParkingUtils.PARKACTIVITYTYPE).getCapacity(); + for (Id fac : parkingFacilitiesAtLink) { + allSpaces += this.parkingFacilities.get(fac).getActivityOptions().get(ParkingUtils.ParkingStageInteractionType).getCapacity(); } } return allSpaces; } - public double getNrOfFreeParkingSpacesOnLink (Id linkId){ + public double getNrOfFreeParkingSpacesOnLink(Id linkId) { double allFreeSpaces = 0; Set> parkingFacilitiesAtLink = this.facilitiesPerLink.get(linkId); if (parkingFacilitiesAtLink == null) { return 0; } else { - for (Id fac : parkingFacilitiesAtLink){ - int cap = (int) this.parkingFacilities.get(fac).getActivityOptions().get(ParkingUtils.PARKACTIVITYTYPE).getCapacity(); + for (Id fac : parkingFacilitiesAtLink) { + int cap = (int) this.parkingFacilities.get(fac).getActivityOptions().get(ParkingUtils.ParkingStageInteractionType).getCapacity(); allFreeSpaces += (cap - this.occupation.get(fac).intValue()); } } @@ -243,11 +293,11 @@ public Map, ActivityFacility> getParkingFacilities() { return this.parkingFacilities; } - public void registerRejectedReservation(double now){ + public void registerRejectedReservation(double now) { rejectedReservationsByTime.get(getTimeSlotIndex(now) * timeBinSize).increment(); } - public TreeSet getTimeSteps(){ + public TreeSet getTimeSteps() { TreeSet timeSteps = new TreeSet<>(); int slotIndex = 0; while (slotIndex <= maxSlotIndex) { @@ -261,15 +311,77 @@ private int getTimeSlotIndex(final double time) { if (time > this.maxTime) { return this.maxSlotIndex; } - return ((int)time / this.timeBinSize); + return ((int) time / this.timeBinSize); + } + + /** + * Gives the duration of the staging activity of parking + * + * @return + */ + public double getParkStageActivityDuration() { + return psConfigGroup.getParkduration(); + } + + /** + * Gives the duration of the staging activity of unparking + * + * @return + */ + public double getUnParkStageActivityDuration() { + return psConfigGroup.getUnparkduration(); } @Override public void reset(int iteration) { - for (Id fac : this.rejectedReservations.keySet()) { - this.rejectedReservations.get(fac).setValue(0); + for (Id fac : this.rejectedParkingRequest.keySet()) { + this.rejectedParkingRequest.get(fac).setValue(0); this.reservationsRequests.get(fac).setValue(0); this.numberOfParkedVehicles.get(fac).setValue(0); + this.numberOfWaitingActivities.get(fac).setValue(0); + } + waitingVehicles.clear(); + } + + public void addVehicleForWaitingForParking(Id linkId, Id vehicleId, double now) { +// System.out.println(now + ": vehicle " +vehicleId.toString() + " starts waiting here: " + linkId.toString()); + waitingVehicles.get(linkId).put(now + getParkStageActivityDuration() + 1, vehicleId); + for (Id fac : this.facilitiesPerLink.get(linkId)) { + this.numberOfWaitingActivities.get(fac).increment(); + break; + } + + } + + public void checkFreeCapacitiesForWaitingVehicles(QSim qSim, double now) { + for (Id linkId : waitingVehicles.keySet()) { + if (!waitingVehicles.get(linkId).isEmpty()) { + for (Id fac : this.facilitiesPerLink.get(linkId)) { + int cap = (int) this.parkingFacilities.get(fac).getActivityOptions().get(ParkingUtils.ParkingStageInteractionType).getCapacity(); + while (this.occupation.get(fac).intValue() < cap && !waitingVehicles.get(linkId).isEmpty()) { + double startWaitingTime = waitingVehicles.get(linkId).firstKey(); + if (startWaitingTime > now) + break; + Id vehcileId = waitingVehicles.get(linkId).remove(startWaitingTime); + DynAgent agent = (DynAgent) qSim.getAgents().get(Id.createPersonId(vehcileId.toString())); + reserveSpaceIfVehicleCanParkHere(vehcileId, linkId); + agent.endActivityAndComputeNextState(now); + qsim.rescheduleActivityEnd(agent); + } + } + } } } + + public void setQSim(QSim qSim) { + qsim = qSim; + } + + public void registerStayFromGetOffUntilGetIn(Id vehcileId) { + this.numberOfStaysFromGetOffUntilGetIn.get(parkingLocations.get(vehcileId)).increment(); + } + + public void registerParkingBeforeGetIn(Id vehcileId) { + this.numberOfParkingBeforeGetIn.get(parkingLocations.get(vehcileId)).increment(); + } } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/ZoneParkingManager.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/ZoneParkingManager.java index 5311933db84..b9fbebe4699 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/ZoneParkingManager.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/manager/ZoneParkingManager.java @@ -1,5 +1,5 @@ /** - * + * */ package org.matsim.contrib.parking.parkingsearch.manager; @@ -23,90 +23,92 @@ */ public class ZoneParkingManager extends FacilityBasedParkingManager { - private HashMap>> linksOfZone; - private HashMap totalCapOfZone; - private HashMap occupationOfZone; - + private HashMap>> linksOfZone; + private HashMap totalCapOfZone; + private HashMap occupationOfZone; + /** * @param scenario */ @Inject public ZoneParkingManager(Scenario scenario, String[] pathToZoneTxtFiles) { super(scenario); - - this.linksOfZone = new HashMap>>(); - this.totalCapOfZone = new HashMap(); - this.occupationOfZone = new HashMap(); - - for(String zone: pathToZoneTxtFiles){ + + this.linksOfZone = new HashMap>>(); + this.totalCapOfZone = new HashMap(); + this.occupationOfZone = new HashMap(); + + for (String zone : pathToZoneTxtFiles) { readZone(zone); } - - for(String zone: this.linksOfZone.keySet()){ + + for (String zone : this.linksOfZone.keySet()) { calculateTotalZoneParkCapacity(zone); - this.occupationOfZone.put(zone,0.0); + this.occupationOfZone.put(zone, 0.0); } } - + /** * reads in a tabular file that declares which link id's are in the monitored zone - * the part between the last '/' and the file type extension in the given path is considered to be the zone name + * the part between the last '/' and the file type extension in the given path is considered to be the zone name * @param pathToZoneFile */ - void readZone(String pathToZoneFile){ - String zone = pathToZoneFile.substring(pathToZoneFile.lastIndexOf("/")+1, pathToZoneFile.lastIndexOf(".")); - + void readZone(String pathToZoneFile) { + String zone = pathToZoneFile.substring(pathToZoneFile.lastIndexOf("/") + 1, pathToZoneFile.lastIndexOf(".")); + HashSet> links = new HashSet>(); - + TabularFileParserConfig config = new TabularFileParserConfig(); - config.setDelimiterTags(new String[] {"\t"}); - config.setFileName(pathToZoneFile); - config.setCommentTags(new String[] { "#" }); - new TabularFileParser().parse(config, new TabularFileHandler() { + config.setDelimiterTags(new String[]{"\t"}); + config.setFileName(pathToZoneFile); + config.setCommentTags(new String[]{"#"}); + new TabularFileParser().parse(config, new TabularFileHandler() { @Override public void startRow(String[] row) { Id linkId = Id.createLinkId(row[0]); links.add(linkId); } - - }); - - this.linksOfZone.put(zone, links); + + }); + + this.linksOfZone.put(zone, links); } - - private void calculateTotalZoneParkCapacity(String zoneName){ + + private void calculateTotalZoneParkCapacity(String zoneName) { double cap = 0.0; - for(Id link : this.linksOfZone.get(zoneName)){ + for (Id link : this.linksOfZone.get(zoneName)) { cap += getNrOfAllParkingSpacesOnLink(link); - } + } this.totalCapOfZone.put(zoneName, cap); } - + @Override public boolean parkVehicleHere(Id vehicleId, Id linkId, double time) { if (parkVehicleAtLink(vehicleId, linkId, time)) { - for(String zone : this.linksOfZone.keySet()){ - if(linksOfZone.get(zone).contains(linkId) && this.facilitiesPerLink.containsKey(linkId)){ + for (String zone : this.linksOfZone.keySet()) { + if (linksOfZone.get(zone).contains(linkId) && this.facilitiesPerLink.containsKey(linkId)) { double newOcc = this.occupationOfZone.get(zone) + 1; - if(this.totalCapOfZone.get(zone) vehicleId, Id linkId, double time) { if (!this.parkingLocations.containsKey(vehicleId)) { @@ -115,35 +117,36 @@ public boolean unParkVehicleHere(Id vehicleId, Id linkId, double } else { Id fac = this.parkingLocations.remove(vehicleId); this.occupation.get(fac).decrement(); - + Id parkingLink = this.parkingFacilities.get(fac).getLinkId(); - for(String zone : this.linksOfZone.keySet()){ - if(linksOfZone.get(zone).contains(parkingLink)){ + for (String zone : this.linksOfZone.keySet()) { + if (linksOfZone.get(zone).contains(parkingLink)) { double newOcc = this.occupationOfZone.get(zone) - 1; - if(newOcc < 0 ){ - //in iteration 0 agents can "leave parking spaces" (get into traffic), but the manager didn't record them to be parked + if (newOcc < 0) { + //in iteration 0 agents can "leave parking spaces" (get into traffic), but the manager didn't record them to be parked newOcc = 0; } - this.occupationOfZone.put(zone,newOcc); + this.occupationOfZone.put(zone, newOcc); } } - return true; + return true; } } - - - public double getOccupancyRatioOfZone(String zone){ - if(!(this.linksOfZone.keySet().contains(zone))) throw new RuntimeException("zone " + zone + " was not defined. thus, could'nt calculate occupancy ratio."); + + + public double getOccupancyRatioOfZone(String zone) { + if (!(this.linksOfZone.keySet().contains(zone))) + throw new RuntimeException("zone " + zone + " was not defined. thus, could'nt calculate occupancy ratio."); return (this.occupationOfZone.get(zone) / this.totalCapOfZone.get(zone)); } - - public Set getZones(){ + + public Set getZones() { return this.linksOfZone.keySet(); } - - public double getTotalCapacityOfZone(String zone){ + + public double getTotalCapacityOfZone(String zone) { return this.totalCapOfZone.get(zone); } - + } diff --git a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/search/NearestParkingSpotSearchLogic.java b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/search/NearestParkingSpotSearchLogic.java index 041e74c2198..d87bf0408fe 100644 --- a/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/search/NearestParkingSpotSearchLogic.java +++ b/contribs/parking/src/main/java/org/matsim/contrib/parking/parkingsearch/search/NearestParkingSpotSearchLogic.java @@ -49,6 +49,7 @@ public class NearestParkingSpotSearchLogic implements ParkingSearchLogic { private NetworkRoute actualRoute = null; private final boolean canReserveParkingSlot; private final boolean canCheckParkingCapacitiesInAdvanced; + private double distanceFromBaseToAttraction = Double.NaN; private boolean useRandomLinkChoice; private int currentLinkIdx; private final HashSet> triedParking; @@ -79,22 +80,32 @@ public NearestParkingSpotSearchLogic(Network network, ParkingRouter parkingRoute * @param baseLinkId linkId of the origin destination where the parkingSearch starts */ public Id getNextLink(Id currentLinkId, Id baseLinkId, Id vehicleId, String mode, double now, - double maxParkingDuration, double nextPickupTime) { - + double maxParkingDuration, double nextPickupTime, boolean passangerInteractionAtParkingFacilityAtEndOfLeg, + Coord coordOfAttraction) { + double maxAdditionalDistanceToAttraction = Double.MAX_VALUE; + // if a passenger interaction take place at a facility the walking distance to the attraction should be not extended by the value of maxAdditionalDistanceToAttraction + if (passangerInteractionAtParkingFacilityAtEndOfLeg) { + if (Double.isNaN(distanceFromBaseToAttraction)) + findDistanceBetweenBaseLinkAndAttraction(baseLinkId, coordOfAttraction); + maxAdditionalDistanceToAttraction = 200.; + } if (actualRoute == null) { - actualRoute = findRouteToNearestParkingFacility(baseLinkId, currentLinkId, canCheckParkingCapacitiesInAdvanced, now, maxParkingDuration); - checkIfDrivingToNextParkingLocationIsPossible(currentLinkId, baseLinkId, now, nextPickupTime); - if (actualRoute != null) { - actualRoute.setVehicleId(vehicleId); - } + actualRoute = findRouteToNearestParkingFacility(baseLinkId, currentLinkId, canCheckParkingCapacitiesInAdvanced, now, + maxParkingDuration, + passangerInteractionAtParkingFacilityAtEndOfLeg, maxAdditionalDistanceToAttraction, coordOfAttraction); + if (!passangerInteractionAtParkingFacilityAtEndOfLeg) + checkIfDrivingToNextParkingLocationIsPossible(currentLinkId, baseLinkId, now, nextPickupTime); triedParking.clear(); } else if (currentLinkId.equals(actualRoute.getEndLinkId()) && !skipParkingActivity) { currentLinkIdx = 0; - actualRoute = findRouteToNearestParkingFacility(baseLinkId, currentLinkId, canCheckParkingCapacitiesInAdvanced, now, maxParkingDuration); - checkIfDrivingToNextParkingLocationIsPossible(currentLinkId, baseLinkId, now, nextPickupTime); - if (actualRoute != null) { - actualRoute.setVehicleId(vehicleId); - } + actualRoute = findRouteToNearestParkingFacility(baseLinkId, currentLinkId, canCheckParkingCapacitiesInAdvanced, now, + maxParkingDuration, + passangerInteractionAtParkingFacilityAtEndOfLeg, maxAdditionalDistanceToAttraction, coordOfAttraction); + if (!passangerInteractionAtParkingFacilityAtEndOfLeg) + checkIfDrivingToNextParkingLocationIsPossible(currentLinkId, baseLinkId, now, nextPickupTime); + } + if (actualRoute != null) { + actualRoute.setVehicleId(vehicleId); } //if no possible parking was found. The vehicle takes a random next link. Background assumption: parking only at given parking slots if (actualRoute == null) { @@ -111,6 +122,20 @@ public Id getNextLink(Id currentLinkId, Id baseLinkId, Id baseLinkId, Coord coordOfAttraction) { + for (ActivityFacility activityFacility : activityFacilities.values()) { + if (activityFacility.getLinkId().equals(baseLinkId)) + distanceFromBaseToAttraction = NetworkUtils.getEuclideanDistance(activityFacility.getCoord(), + coordOfAttraction); + } + } + /** * Checks if it is possible to drive to the new parking facility and to drive back to the base without extending the startTime of the following activity. * If the resulting parking time at the new facility is less then 5 minutes the vehicle will drive directly to the next activity location. @@ -175,7 +200,9 @@ public boolean isUseRandomLinkChoice() { } private NetworkRoute findRouteToNearestParkingFacility(Id baseLinkId, Id currentLinkId, boolean canCheckParkingCapacitiesInAdvanced, - double now, double maxParkingDuration) { + double now, double maxParkingDuration, + boolean passangerInteractionAtParkingFacilityAtEndOfLeg, double maxDistanceFromBase, + Coord coordOfAttraction) { TreeMap euclideanDistanceToParkingFacilities = new TreeMap<>(); ActivityFacility nearstActivityFacility = null; NetworkRoute selectedRoute = null; @@ -183,29 +210,31 @@ private NetworkRoute findRouteToNearestParkingFacility(Id baseLinkId, Id now || parkingOptions.getOpeningTimes().first().getEndTime() < latestEndOfParking) - continue; + if (parkingOptions.getOpeningTimes().first().getStartTime() > now && parkingOptions.getOpeningTimes().first().getEndTime() < latestEndOfParking) + continue; } - //check if approx. the max parking time at facility will not exceed + //check if approx. the max parking time at facility will not exceed, assumption: "parking duration - 30 minutes" is parking Time. if (activityFacility.getAttributes().getAsMap().containsKey("maxParkingDurationInHours")) { //TODO vielleicht etwas sparsamer machen double maxParkingDurationAtFacility = 3600 * (double) activityFacility.getAttributes().getAsMap().get("maxParkingDurationInHours"); - if (maxParkingDuration > maxParkingDurationAtFacility) + if (maxParkingDuration - 30*60 > maxParkingDurationAtFacility) continue; - double expectedTravelTimeFromParkingToBase = getExpectedTravelTime(baseLinkId, now, activityFacility.getLinkId()); - double expectedTravelTimeFromCurrentToParking = getExpectedTravelTime(activityFacility.getLinkId(), now, currentLinkId); - double expectedParkingTime = maxParkingDuration - expectedTravelTimeFromCurrentToParking - expectedTravelTimeFromParkingToBase; - if (expectedParkingTime > maxParkingDurationAtFacility) + } + + //TODO beschreiben was passiert + if (passangerInteractionAtParkingFacilityAtEndOfLeg) { + double distanceBetweenThisParkingFacilityAndTheAttraction = NetworkUtils.getEuclideanDistance(activityFacility.getCoord(), + coordOfAttraction); + if (distanceBetweenThisParkingFacilityAndTheAttraction - distanceFromBaseToAttraction > maxDistanceFromBase) continue; } // create Euclidean distances to the parking activities to find routes only to the nearest facilities in the next step @@ -213,7 +242,11 @@ private NetworkRoute findRouteToNearestParkingFacility(Id baseLinkId, Id baseLinkId, Id maxParkingDurationAtFacility) + continue; + } counter++; + if (passangerInteractionAtParkingFacilityAtEndOfLeg && euclideanDistanceToParkingFacilities.size() > triedParking.size()) + if (triedParking.contains(activityFacility.getId())) + continue; + if (passangerInteractionAtParkingFacilityAtEndOfLeg && euclideanDistanceToParkingFacilities.size() == triedParking.size()) + triedParking.clear(); NetworkRoute possibleRoute = this.parkingRouter.getRouteFromParkingToDestination(activityFacility.getLinkId(), now, currentLinkId); + // reason is that we expect that the driver will always take the nearest possible getOff point to reduce the walk distance for the guests + if (passangerInteractionAtParkingFacilityAtEndOfLeg){ + selectedRoute = possibleRoute; + nearstActivityFacility = activityFacility; + break; + } double travelTimeToParking = possibleRoute.getTravelTime().seconds(); double travelTimeFromParking = travelTimeToParking; if (!baseLinkId.equals(currentLinkId)) { @@ -276,6 +328,7 @@ public void reset() { actualRoute = null; currentLinkIdx = 0; skipParkingActivity = false; + distanceFromBaseToAttraction = Double.NaN; } } diff --git a/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/optimizer/ETaxiModeOptimizerQSimModule.java b/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/optimizer/ETaxiModeOptimizerQSimModule.java index 3fd984a8a7d..3c42d7111c2 100644 --- a/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/optimizer/ETaxiModeOptimizerQSimModule.java +++ b/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/optimizer/ETaxiModeOptimizerQSimModule.java @@ -35,7 +35,7 @@ import org.matsim.contrib.etaxi.ETaxiScheduler; import org.matsim.contrib.etaxi.util.ETaxiStayTaskEndTimeCalculator; import org.matsim.contrib.ev.infrastructure.ChargingInfrastructure; -import org.matsim.contrib.ev.infrastructure.ChargingInfrastructures; +import org.matsim.contrib.ev.infrastructure.ChargingInfrastructureUtils; import org.matsim.contrib.taxi.analysis.TaxiEventSequenceCollector; import org.matsim.contrib.taxi.optimizer.TaxiOptimizer; import org.matsim.contrib.taxi.run.TaxiConfigGroup; @@ -91,8 +91,8 @@ public TaxiOptimizer get() { }); bindModal(ChargingInfrastructure.class).toProvider(modalProvider( - getter -> ChargingInfrastructures.createModalNetworkChargers(getter.get(ChargingInfrastructure.class), - getter.getModal(Network.class), getMode()))).asEagerSingleton(); + getter -> ChargingInfrastructureUtils.createModalNetworkChargers(getter.get(ChargingInfrastructure.class ), + getter.getModal(Network.class), getMode() ))).asEagerSingleton(); addModalComponent(ETaxiScheduler.class, new ModalProviders.AbstractProvider<>(taxiCfg.getMode(), DvrpModes::mode) { diff --git a/contribs/vsp/pom.xml b/contribs/vsp/pom.xml index 96a0cd8ca37..99614d63e78 100644 --- a/contribs/vsp/pom.xml +++ b/contribs/vsp/pom.xml @@ -174,12 +174,12 @@ org.openjfx javafx-graphics - 21 + 21.0.1 com.graphhopper graphhopper-core - 7.0 + 8.0 diff --git a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/FreightAnalysisEventHandler.java b/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/FreightAnalysisEventHandler.java index 5a9daccf1cf..2f322e8640f 100644 --- a/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/FreightAnalysisEventHandler.java +++ b/contribs/vsp/src/main/java/org/matsim/freight/carriers/analysis/FreightAnalysisEventHandler.java @@ -36,10 +36,10 @@ import org.matsim.freight.carriers.events.CarrierServiceStartEvent; import org.matsim.freight.carriers.events.CarrierShipmentDeliveryEndEvent; import org.matsim.freight.carriers.events.CarrierShipmentPickupEndEvent; -import org.matsim.freight.carriers.events.eventhandler.FreightServiceEndEventHandler; -import org.matsim.freight.carriers.events.eventhandler.FreightServiceStartEventHandler; -import org.matsim.freight.carriers.events.eventhandler.FreightShipmentDeliveryEventHandler; -import org.matsim.freight.carriers.events.eventhandler.FreightShipmentPickupEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierServiceEndEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierServiceStartEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierShipmentDeliveryEndEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierShipmentPickupEndEventHandler; import org.matsim.core.network.NetworkUtils; import org.matsim.vehicles.Vehicle; import org.matsim.vehicles.Vehicles; @@ -59,7 +59,7 @@ * */ @Deprecated(since = "apr23") -class FreightAnalysisEventHandler implements ActivityStartEventHandler, LinkEnterEventHandler, LinkLeaveEventHandler, PersonEntersVehicleEventHandler, PersonLeavesVehicleEventHandler, FreightShipmentPickupEventHandler, FreightShipmentDeliveryEventHandler, FreightServiceStartEventHandler, FreightServiceEndEventHandler { +class FreightAnalysisEventHandler implements ActivityStartEventHandler, LinkEnterEventHandler, LinkLeaveEventHandler, PersonEntersVehicleEventHandler, PersonLeavesVehicleEventHandler, CarrierShipmentPickupEndEventHandler, CarrierShipmentDeliveryEndEventHandler, CarrierServiceStartEventHandler, CarrierServiceEndEventHandler { private final static Logger log = LogManager.getLogger(FreightAnalysisEventHandler.class); private final Vehicles vehicles; diff --git a/contribs/vsp/src/main/java/playground/vsp/ev/ElectricFleetUpdater.java b/contribs/vsp/src/main/java/playground/vsp/ev/ElectricFleetUpdater.java index e89f9fcf55b..5b5ab616092 100644 --- a/contribs/vsp/src/main/java/playground/vsp/ev/ElectricFleetUpdater.java +++ b/contribs/vsp/src/main/java/playground/vsp/ev/ElectricFleetUpdater.java @@ -24,7 +24,7 @@ import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.Population; import org.matsim.contrib.ev.fleet.ElectricFleetSpecification; -import org.matsim.contrib.ev.fleet.ElectricVehicleSpecificationImpl; +import org.matsim.contrib.ev.fleet.ElectricFleetUtils; import org.matsim.core.controler.events.IterationStartsEvent; import org.matsim.core.controler.listener.IterationStartsListener; import org.matsim.core.router.TripStructureUtils; @@ -56,6 +56,6 @@ private void registerEVs(Plan plan) { var modalVehicles = TripStructureUtils.getLegs(plan).stream() .map(leg -> vehicles.getVehicles().get(VehicleUtils.getVehicleId(plan.getPerson(), leg.getMode()))) .toList(); - ElectricVehicleSpecificationImpl.createAndAddVehicleSpecificationsFromMatsimVehicles(fleetSpecification, modalVehicles); + ElectricFleetUtils.createAndAddVehicleSpecificationsFromMatsimVehicles(fleetSpecification, modalVehicles ); } } diff --git a/contribs/vsp/src/main/java/playground/vsp/ev/RunUrbanEVExample.java b/contribs/vsp/src/main/java/playground/vsp/ev/RunUrbanEVExample.java index e5b374733f6..97d90f45650 100644 --- a/contribs/vsp/src/main/java/playground/vsp/ev/RunUrbanEVExample.java +++ b/contribs/vsp/src/main/java/playground/vsp/ev/RunUrbanEVExample.java @@ -50,7 +50,7 @@ import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.population.Person; import org.matsim.contrib.ev.EvConfigGroup; -import org.matsim.contrib.ev.fleet.ElectricVehicleSpecifications; +import org.matsim.contrib.ev.fleet.ElectricFleetUtils; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.groups.RoutingConfigGroup; @@ -144,11 +144,11 @@ static void createAndRegisterPersonalCarAndBikeVehicles(Scenario scenario) { VehicleType.class)); //TODO should at least have a suffix "_car" VehicleUtils.setHbefaTechnology(carVehicleType.getEngineInformation(), "electricity"); VehicleUtils.setEnergyCapacity(carVehicleType.getEngineInformation(), CAR_BATTERY_CAPACITY_kWh); - ElectricVehicleSpecifications.setChargerTypes(carVehicleType.getEngineInformation(), Arrays.asList("a", "b", "default")); + ElectricFleetUtils.setChargerTypes(carVehicleType.getEngineInformation(), Arrays.asList("a", "b", "default" ) ); scenario.getVehicles().addVehicleType(carVehicleType); Vehicle carVehicle = vehicleFactory.createVehicle(VehicleUtils.createVehicleId(person, TransportMode.car), carVehicleType); - ElectricVehicleSpecifications.setInitialSoc(carVehicle, CAR_INITIAL_SOC); + ElectricFleetUtils.setInitialSoc(carVehicle, CAR_INITIAL_SOC ); scenario.getVehicles().addVehicle(carVehicle); VehicleType bikeVehicleType = vehicleFactory.createVehicleType( diff --git a/contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVTripsPlanner.java b/contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVTripsPlanner.java index 0449190e8f6..b68f4d5bcff 100644 --- a/contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVTripsPlanner.java +++ b/contribs/vsp/src/main/java/playground/vsp/ev/UrbanEVTripsPlanner.java @@ -54,10 +54,7 @@ import org.matsim.contrib.ev.charging.ChargingPower; import org.matsim.contrib.ev.discharging.AuxEnergyConsumption; import org.matsim.contrib.ev.discharging.DriveEnergyConsumption; -import org.matsim.contrib.ev.fleet.ElectricFleetSpecification; -import org.matsim.contrib.ev.fleet.ElectricVehicle; -import org.matsim.contrib.ev.fleet.ElectricVehicleImpl; -import org.matsim.contrib.ev.fleet.ElectricVehicleSpecification; +import org.matsim.contrib.ev.fleet.*; import org.matsim.contrib.ev.infrastructure.ChargerSpecification; import org.matsim.contrib.ev.infrastructure.ChargingInfrastructureSpecification; import org.matsim.core.config.Config; @@ -208,8 +205,8 @@ private void processPlans(Map>> selectedEVPlans) { */ ElectricVehicleSpecification evSpec = electricFleetSpecification.getVehicleSpecifications().get(Id.create(ev, Vehicle.class)); Leg legWithCriticalSOC; - ElectricVehicle pseudoVehicle = ElectricVehicleImpl.create(evSpec, driveConsumptionFactory, auxConsumptionFactory, - chargingPowerFactory); + ElectricVehicle pseudoVehicle = ElectricFleetUtils.create(evSpec, driveConsumptionFactory, auxConsumptionFactory, + chargingPowerFactory ); //TODO: erase hardcoding of car mode! List evCarLegs = TripStructureUtils.getLegs(modifiablePlan) .stream() diff --git a/contribs/vsp/src/main/java/playground/vsp/ev/UrbanVehicleChargingHandler.java b/contribs/vsp/src/main/java/playground/vsp/ev/UrbanVehicleChargingHandler.java index 543080da322..592722998fe 100644 --- a/contribs/vsp/src/main/java/playground/vsp/ev/UrbanVehicleChargingHandler.java +++ b/contribs/vsp/src/main/java/playground/vsp/ev/UrbanVehicleChargingHandler.java @@ -30,7 +30,7 @@ import org.matsim.contrib.ev.fleet.ElectricVehicle; import org.matsim.contrib.ev.infrastructure.Charger; import org.matsim.contrib.ev.infrastructure.ChargingInfrastructure; -import org.matsim.contrib.ev.infrastructure.ChargingInfrastructures; +import org.matsim.contrib.ev.infrastructure.ChargingInfrastructureUtils; import org.matsim.core.events.MobsimScopeEventHandler; import org.matsim.core.utils.collections.Tuple; import org.matsim.vehicles.Vehicle; @@ -67,7 +67,7 @@ class UrbanVehicleChargingHandler UrbanVehicleChargingHandler(ChargingInfrastructure chargingInfrastructure, ElectricFleet electricFleet) { this.chargingInfrastructure = chargingInfrastructure; this.electricFleet = electricFleet; - this.chargersAtLinks = ChargingInfrastructures.getChargersAtLinks(chargingInfrastructure); + this.chargersAtLinks = ChargingInfrastructureUtils.getChargersAtLinks(chargingInfrastructure ); } /** diff --git a/contribs/vsp/src/test/java/org/matsim/freight/carriers/analysis/MyServiceTrackerEventHandler.java b/contribs/vsp/src/test/java/org/matsim/freight/carriers/analysis/MyServiceTrackerEventHandler.java index 43c9dd2d524..ae51676c57b 100644 --- a/contribs/vsp/src/test/java/org/matsim/freight/carriers/analysis/MyServiceTrackerEventHandler.java +++ b/contribs/vsp/src/test/java/org/matsim/freight/carriers/analysis/MyServiceTrackerEventHandler.java @@ -29,11 +29,11 @@ import org.matsim.freight.carriers.Carriers; import org.matsim.freight.carriers.events.CarrierServiceEndEvent; import org.matsim.freight.carriers.events.CarrierServiceStartEvent; -import org.matsim.freight.carriers.events.eventhandler.FreightServiceEndEventHandler; -import org.matsim.freight.carriers.events.eventhandler.FreightServiceStartEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierServiceEndEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierServiceStartEventHandler; import org.matsim.vehicles.Vehicles; - class MyServiceTrackerEventHandler implements ActivityStartEventHandler, FreightServiceStartEventHandler, FreightServiceEndEventHandler { + class MyServiceTrackerEventHandler implements ActivityStartEventHandler, CarrierServiceStartEventHandler, CarrierServiceEndEventHandler { private final Vehicles vehicles; private final Network network; private final Carriers carriers; diff --git a/contribs/vsp/src/test/java/org/matsim/freight/carriers/analysis/MyShipmentTrackerEventHandler.java b/contribs/vsp/src/test/java/org/matsim/freight/carriers/analysis/MyShipmentTrackerEventHandler.java index 35b455b8944..178652c1c7d 100644 --- a/contribs/vsp/src/test/java/org/matsim/freight/carriers/analysis/MyShipmentTrackerEventHandler.java +++ b/contribs/vsp/src/test/java/org/matsim/freight/carriers/analysis/MyShipmentTrackerEventHandler.java @@ -29,11 +29,11 @@ import org.matsim.freight.carriers.Carriers; import org.matsim.freight.carriers.events.CarrierShipmentDeliveryEndEvent; import org.matsim.freight.carriers.events.CarrierShipmentPickupEndEvent; -import org.matsim.freight.carriers.events.eventhandler.FreightShipmentDeliveryEventHandler; -import org.matsim.freight.carriers.events.eventhandler.FreightShipmentPickupEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierShipmentDeliveryEndEventHandler; +import org.matsim.freight.carriers.events.eventhandler.CarrierShipmentPickupEndEventHandler; import org.matsim.vehicles.Vehicles; -public class MyShipmentTrackerEventHandler implements ActivityStartEventHandler, FreightShipmentPickupEventHandler, FreightShipmentDeliveryEventHandler { +public class MyShipmentTrackerEventHandler implements ActivityStartEventHandler, CarrierShipmentPickupEndEventHandler, CarrierShipmentDeliveryEndEventHandler { private final Vehicles vehicles; private final Network network; @@ -69,7 +69,7 @@ public void handleEvent(CarrierShipmentPickupEndEvent event) { @Override public void reset(int iteration) { - FreightShipmentPickupEventHandler.super.reset(iteration); + CarrierShipmentPickupEndEventHandler.super.reset(iteration); } @Override diff --git a/contribs/vsp/src/test/java/playground/vsp/ev/TransferFinalSocToNextIterTest.java b/contribs/vsp/src/test/java/playground/vsp/ev/TransferFinalSocToNextIterTest.java index b77b0352fc0..172fc201ad2 100644 --- a/contribs/vsp/src/test/java/playground/vsp/ev/TransferFinalSocToNextIterTest.java +++ b/contribs/vsp/src/test/java/playground/vsp/ev/TransferFinalSocToNextIterTest.java @@ -28,9 +28,8 @@ import org.junit.Test; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; +import org.matsim.contrib.ev.fleet.ElectricFleetUtils; import org.matsim.contrib.ev.fleet.ElectricVehicleSpecification; -import org.matsim.contrib.ev.fleet.ElectricVehicleSpecificationImpl; -import org.matsim.contrib.ev.fleet.ElectricVehicleSpecifications; import org.matsim.core.controler.Controler; import org.matsim.core.controler.events.AfterMobsimEvent; import org.matsim.core.controler.events.BeforeMobsimEvent; @@ -56,7 +55,7 @@ public void test() { scenario.getConfig().controller().setOutputDirectory("test/output/playground/vsp/ev/FinalSoc2VehicleTypeTest/"); var vehicle1 = scenario.getVehicles().getVehicles().get(Id.create("Triple Charger_car", Vehicle.class)); - ElectricVehicleSpecifications.setInitialSoc(vehicle1, INITIAL_SOC); + ElectricFleetUtils.setInitialSoc(vehicle1, INITIAL_SOC ); //controler Controler controler = RunUrbanEVExample.prepareControler(scenario); @@ -69,7 +68,7 @@ public void test() { // testSOCIsDumpedIntoVehicleType //agent has driven the car so SOC should have changed and should be dumped into the vehicle type var vehicle = scenario.getVehicles().getVehicles().get(Id.create("Triple Charger_car", Vehicle.class)); - var evSpec = new ElectricVehicleSpecificationImpl(vehicle); + var evSpec = ElectricFleetUtils.createElectricVehicleSpecificationDefaultImpl(vehicle ); Assert.assertNotEquals(evSpec.getInitialSoc(), INITIAL_SOC); Assert.assertEquals(0.7273605127621898, evSpec.getInitialSoc(), MatsimTestUtils.EPSILON); //should not be fully charged @@ -86,7 +85,7 @@ private static class SOCHandler implements BeforeMobsimListener, AfterMobsimList SOCHandler(Scenario scenario) { var car = scenario.getVehicles().getVehicles().get(Id.create("Triple Charger_car", Vehicle.class)); - evSpec = new ElectricVehicleSpecificationImpl(car); + evSpec = ElectricFleetUtils.createElectricVehicleSpecificationDefaultImpl(car ); } @Override diff --git a/matsim/pom.xml b/matsim/pom.xml index ff071fb253a..eaff0f036bb 100644 --- a/matsim/pom.xml +++ b/matsim/pom.xml @@ -117,7 +117,7 @@ org.apache.maven.plugins maven-surefire-report-plugin - 3.1.2 + 3.2.1 diff --git a/pom.xml b/pom.xml index 44d423b0f53..3582b5ca0c9 100644 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ 17 - 2.20.0 + 2.21.1 29.2 1.19.0 7.0.0 @@ -177,7 +177,7 @@ org.glassfish.jaxb jaxb-bom - 4.0.3 + 4.0.4 pom import @@ -185,7 +185,7 @@ com.google.errorprone error_prone_annotations - 2.22.0 + 2.23.0 @@ -346,7 +346,7 @@ - 3.6.3 + 3.8 @@ -382,12 +382,12 @@ org.apache.maven.plugins maven-surefire-plugin - 3.1.2 + 3.2.1 org.apache.maven.plugins maven-failsafe-plugin - 3.1.2 + 3.2.1 org.apache.maven.plugins @@ -469,7 +469,7 @@ org.jacoco jacoco-maven-plugin - 0.8.10 + 0.8.11 default-prepare-agent