Skip to content

Commit

Permalink
Merge pull request #325 from matsim-org/bicycleScoring
Browse files Browse the repository at this point in the history
Adaptions in bicycle code for routing, scoring, and other vehicle interaction
  • Loading branch information
dziemke authored Aug 27, 2018
2 parents eeeb2fa + 9525184 commit d4fd09c
Show file tree
Hide file tree
Showing 54 changed files with 24,549 additions and 841 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* See also COPYING, LICENSE and WARRANTY file *
* *
* *********************************************************************** */
package org.matsim.contrib.bicycle.run;
package org.matsim.contrib.bicycle;

import java.util.Map;
import java.util.TreeMap;
Expand All @@ -34,11 +34,14 @@ public class BicycleConfigGroup extends ConfigGroup {
private static final String INPUT_COMFORT = "marginalUtilityOfComfort_m";
private static final String INPUT_INFRASTRUCTURE = "marginalUtilityOfInfrastructure_m";
private static final String INPUT_GRADIENT = "marginalUtilityOfGradient_m_100m";

public static enum BicycleScoringType {legBased, linkBased};

private String networkAttFile = null;
private double marginalUtilityOfComfort;
private double marginalUtilityOfInfrastructure;
private double marginalUtilityOfGradient;
private BicycleScoringType bicycleScoringType = BicycleScoringType.legBased;

public BicycleConfigGroup() {
super(GROUP_NAME);
Expand Down Expand Up @@ -127,4 +130,12 @@ public void setMarginalUtilityOfGradient_m_100m(final double value) {
public double getMarginalUtilityOfGradient_m_100m() {
return this.marginalUtilityOfGradient;
}

public void setBicycleScoringType(final BicycleScoringType value) {
this.bicycleScoringType = value;
}

public BicycleScoringType getBicycleScoringType() {
return this.bicycleScoringType;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,4 @@ public final class BicycleLabels {
private BicycleLabels() {
// Don't allow to create instances of this class
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* *********************************************************************** *
* project: org.matsim.* *
* BicycleLegScoring.java *
* *
* *********************************************************************** *
* *
* copyright : (C) 2007 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.bicycle;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.population.Leg;
import org.matsim.core.population.routes.NetworkRoute;
import org.matsim.core.scoring.functions.CharyparNagelLegScoring;
import org.matsim.core.scoring.functions.ScoringParameters;

/**
* @author dziemke
*/
public class BicycleLegScoring extends CharyparNagelLegScoring {
// private static final Logger LOG = Logger.getLogger(BicycleLegScoring.class);

private final double marginalUtilityOfInfrastructure_m;
private final double marginalUtilityOfComfort_m;
private final double marginalUtilityOfGradient_m_100m;

public BicycleLegScoring(final ScoringParameters params, Network network, BicycleConfigGroup bicycleConfigGroup) {
super(params, network);

this.marginalUtilityOfInfrastructure_m = bicycleConfigGroup.getMarginalUtilityOfInfrastructure_m();
this.marginalUtilityOfComfort_m = bicycleConfigGroup.getMarginalUtilityOfComfort_m();
this.marginalUtilityOfGradient_m_100m = bicycleConfigGroup.getMarginalUtilityOfGradient_m_100m();
}

protected double calcLegScore(final double departureTime, final double arrivalTime, final Leg leg) {
// Get leg score from regular CharyparNagelLegScoring
double legScore = super.calcLegScore(departureTime, arrivalTime, leg);
// LOG.warn("----- legScore = " + legScore);

NetworkRoute networkRoute = (NetworkRoute) leg.getRoute();

List<Id<Link>> linkIds = new ArrayList<>();
linkIds.addAll(networkRoute.getLinkIds());
linkIds.add(networkRoute.getEndLinkId());

// Iterate over all links of the route
for (Id<Link> linkId : linkIds) {
double scoreOnLink = BicycleUtilityUtils.computeLinkBasedScore(network.getLinks().get(linkId),
marginalUtilityOfComfort_m, marginalUtilityOfInfrastructure_m, marginalUtilityOfGradient_m_100m);
// LOG.warn("----- link = " + linkId + " -- scoreOnLink = " + scoreOnLink);
legScore += scoreOnLink;
}
return legScore;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* See also COPYING, LICENSE and WARRANTY file *
* *
* *********************************************************************** */
package org.matsim.contrib.bicycle.run;
package org.matsim.contrib.bicycle;

import org.apache.log4j.Logger;
import org.matsim.api.core.v01.Id;
Expand All @@ -26,31 +26,46 @@
import org.matsim.api.core.v01.events.VehicleEntersTrafficEvent;
import org.matsim.api.core.v01.events.VehicleLeavesTrafficEvent;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.population.Person;
import org.matsim.contrib.bicycle.MotorizedInteractionEvent;
import org.matsim.contrib.bicycle.MotorizedInteractionEventHandler;
import org.matsim.core.events.algorithms.Vehicle2DriverEventHandler;
import org.matsim.core.gbl.Gbl;
import org.matsim.core.scoring.SumScoringFunction;
import org.matsim.core.scoring.functions.ModeUtilityParameters;
import org.matsim.core.scoring.functions.ScoringParameters;
import org.matsim.vehicles.Vehicle;

/**
* @author dziemke
*
* This is an alternative to BicycleLegScoring. Currently yields slightly different scores than BicyleLegScoring.
* This link-based scoring should be used when true times spent on an individual link are relevant
* and for the scoring of the interaction with motorized traffic.
*/
public class BicycleScoring implements SumScoringFunction.ArbitraryEventScoring, MotorizedInteractionEventHandler {
private static final Logger LOG = Logger.getLogger(BicycleScoring.class);
public class BicycleLinkScoring implements SumScoringFunction.ArbitraryEventScoring, MotorizedInteractionEventHandler {
private static final Logger LOG = Logger.getLogger(BicycleLinkScoring.class);

protected final ScoringParameters params;

private Scenario scenario;
private BicycleTravelDisutility bicycleTravelDisutility;
private Vehicle2DriverEventHandler delegate = new Vehicle2DriverEventHandler();
private Vehicle2DriverEventHandler vehicle2Driver = new Vehicle2DriverEventHandler();
private Id<Link> previousLink;
private double previousLinkRelativePosition;
private double previousLinkEnterTime;
private double score;
private int carCountOnLink;

public BicycleScoring(Scenario scenario, BicycleTravelTime bicycleTravelTime, BicycleTravelDisutilityFactory bicycleTravelDisutilityFactory) {
this.scenario = scenario;
this.bicycleTravelDisutility = (BicycleTravelDisutility) bicycleTravelDisutilityFactory.createTravelDisutility(bicycleTravelTime);
private final double marginalUtilityOfInfrastructure_m;
private final double marginalUtilityOfComfort_m;
private final double marginalUtilityOfGradient_m_100m;

private static int ccc=0 ;

public BicycleLinkScoring(final ScoringParameters params, Scenario scenario, BicycleConfigGroup bicycleConfigGroup) {
this.params = params;
this.scenario = scenario;

this.marginalUtilityOfInfrastructure_m = bicycleConfigGroup.getMarginalUtilityOfInfrastructure_m();
this.marginalUtilityOfComfort_m = bicycleConfigGroup.getMarginalUtilityOfComfort_m();
this.marginalUtilityOfGradient_m_100m = bicycleConfigGroup.getMarginalUtilityOfGradient_m_100m();
}

@Override public void finish() {}
Expand All @@ -63,11 +78,10 @@ public double getScore() {
@Override
public void handleEvent(Event event) {
if (event instanceof VehicleEntersTrafficEvent) {
// LOG.warn(event.toString());
VehicleEntersTrafficEvent vehEvent = (VehicleEntersTrafficEvent) event;

// Establish connection between driver and vehicle
delegate.handleEvent(vehEvent);
vehicle2Driver.handleEvent(vehEvent);

// No LinkEnterEvent on first link of a leg
previousLink = vehEvent.getLinkId();
Expand All @@ -77,7 +91,6 @@ public void handleEvent(Event event) {

}
if (event instanceof VehicleLeavesTrafficEvent) {
// LOG.warn(event.toString());
VehicleLeavesTrafficEvent vehEvent = (VehicleLeavesTrafficEvent) event;

Id<Vehicle> vehId = vehEvent.getVehicleId();
Expand All @@ -86,12 +99,11 @@ public void handleEvent(Event event) {
calculateScoreForPreviousLink(vehEvent.getLinkId(), enterTime, vehId, travelTime, previousLinkRelativePosition);

// End connection between driver and vehicle
delegate.handleEvent(vehEvent);
vehicle2Driver.handleEvent(vehEvent);
}
if (event instanceof LinkEnterEvent) {
// This only works because setPassLinkEventsToPerson is activated (via ScoringFunctionsForPopulation)
// This only works since ScoringFunctionsForPopulation passes link events to persons; quite new; dz, june'18
// Otherwise ArbitraryEventScoring only handles events that are instance of HasPersonId, which is not the case for LinkEnterEvents
// LOG.warn(event.toString());
LinkEnterEvent linkEnterEvent = (LinkEnterEvent) event;

Id<Vehicle> vehId = linkEnterEvent.getVehicleId();
Expand All @@ -103,34 +115,66 @@ public void handleEvent(Event event) {
carCountOnLink = 0;
previousLinkRelativePosition = 0.;
previousLinkEnterTime = linkEnterEvent.getTime();

}
}
}

private void calculateScoreForPreviousLink(Id<Link> linkId, Double enterTime, Id<Vehicle> vehId, double travelTime, double relativeLinkEnterPosition) {
if (relativeLinkEnterPosition != 1.0) {
Link link = scenario.getNetwork().getLinks().get(linkId);
Person person = scenario.getPopulation().getPersons().get(delegate.getDriverOfVehicle(vehId));
Vehicle vehicle = scenario.getVehicles().getVehicles().get(vehId);
// Link link = scenario.getNetwork().getLinks().get(linkId);
// Person person = scenario.getPopulation().getPersons().get(vehicle2Driver.getDriverOfVehicle(vehId));
// Vehicle vehicle = scenario.getVehicles().getVehicles().get(vehId);

double carScoreOffset = -(this.carCountOnLink * 0.04);
this.score += carScoreOffset;
LOG.warn("----- link = " + linkId + " -- car score offset = " + carScoreOffset);
// LOG.warn("----- link = " + linkId + " -- car score offset = " + carScoreOffset);

double scoreOnLink = BicycleUtilityUtils.computeLinkBasedScore(scenario.getNetwork().getLinks().get(linkId),
marginalUtilityOfComfort_m, marginalUtilityOfInfrastructure_m, marginalUtilityOfGradient_m_100m);
// LOG.warn("----- link = " + linkId + " -- scoreOnLink = " + scoreOnLink);
this.score += scoreOnLink;

this.score += bicycleTravelDisutility.getTravelDisutilityBasedOnTTime(link, enterTime, person, vehicle, travelTime);
// LOG.warn("score = " + score + " -- linkId = " + link.getId() + " -- enterTime = " + enterTime + " -- personId = " + person.getId() + " -- travelTime = " + travelTime);
double timeDistanceBasedScoreComponent = computeTimeDistanceBasedScoreComponent(travelTime, scenario.getNetwork().getLinks().get(linkId).getLength());
// LOG.warn("----- link = " + linkId + " -- timeDistanceBasedScoreComponent = " + timeDistanceBasedScoreComponent);
this.score += timeDistanceBasedScoreComponent;
}
else {
// If agent was already at the end of the link and thus did not travel on it, do nothing
double timeDistanceBasedScoreComponent = computeTimeDistanceBasedScoreComponent(travelTime, 0.);
this.score += timeDistanceBasedScoreComponent;
}
// TODO Use relative position in a more sophisticated way.
}


// Copied and adapted from CharyparNagelLegScoring
protected double computeTimeDistanceBasedScoreComponent(double travelTime, double dist) {
double tmpScore = 0.0;
ModeUtilityParameters modeParams = this.params.modeParams.get("bicycle");
if (modeParams == null) {
throw new RuntimeException("no scoring parameters are defined for bicycle") ;
}
tmpScore += travelTime * modeParams.marginalUtilityOfTraveling_s;
if (modeParams.marginalUtilityOfDistance_m != 0.0 || modeParams.monetaryDistanceCostRate != 0.0) {
if ( Double.isNaN(dist) ) {
if ( ccc<10 ) {
ccc++ ;
Logger.getLogger(this.getClass()).warn("distance is NaN. Will make score of this plan NaN. Possible reason: Simulation does not report " +
"a distance for this trip. Possible reason for that: mode is teleported and router does not " +
"write distance into plan. Needs to be fixed or these plans will die out.") ;
if ( ccc==10 ) {
Logger.getLogger(this.getClass()).warn(Gbl.FUTURE_SUPPRESSED) ;
}
}
}
tmpScore += modeParams.marginalUtilityOfDistance_m * dist;
tmpScore += modeParams.monetaryDistanceCostRate * this.params.marginalUtilityOfMoney * dist;
}
tmpScore += modeParams.constant;
return tmpScore;
}


@Override
public void handleEvent(MotorizedInteractionEvent event) {
// LOG.info("event received from link " + event.getLinkId());
if (event.getLinkId().equals(previousLink)) {
// LOG.warn("USED: Event from link " + event.getLinkId());
this.carCountOnLink++;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,9 @@
* See also COPYING, LICENSE and WARRANTY file *
* *
* *********************************************************************** */
package org.matsim.contrib.bicycle.run;
package org.matsim.contrib.bicycle;

import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.network.Link;
import org.matsim.contrib.bicycle.BicycleUtils;
import org.matsim.contrib.bicycle.MotorizedInteractionEngine;
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.core.controler.AbstractModule;
import org.matsim.core.mobsim.qsim.qnetsimengine.ConfigurableQNetworkFactory;
import org.matsim.core.mobsim.qsim.qnetsimengine.QNetworkFactory;
import org.matsim.core.mobsim.qsim.qnetsimengine.QVehicle;
import org.matsim.core.mobsim.qsim.qnetsimengine.linkspeedcalculator.DefaultLinkSpeedCalculator;
import org.matsim.core.mobsim.qsim.qnetsimengine.linkspeedcalculator.LinkSpeedCalculator;
import org.matsim.vehicles.VehicleType;

import com.google.inject.Provides;
import com.google.inject.Singleton;

/**
* @author smetzler, dziemke
Expand All @@ -46,32 +31,16 @@ public void install() {
bind(BicycleTravelTime.class).asEagerSingleton();
addTravelTimeBinding("bicycle").to(BicycleTravelTime.class);
bind(BicycleTravelDisutilityFactory.class).asEagerSingleton();
addTravelDisutilityFactoryBinding("bicycle").to(BicycleTravelDisutilityFactory.class);
this.bindScoringFunctionFactory().toInstance(new BicycleScoringFunctionFactory());
addTravelDisutilityFactoryBinding("bicycle").to(BicycleTravelDisutilityFactory.class);
bindScoringFunctionFactory().toInstance(new BicycleScoringFunctionFactory());
// The following leads to "Tried proxying org.matsim.core.scoring.ScoringFunctionsForPopulation to support a circular dependency, but it is not an interface."
// bindScoringFunctionFactory().to(BicycleScoringFunctionFactory.class);

if (considerMotorizedInteraction) {
addMobsimListenerBinding().to(MotorizedInteractionEngine.class);
}
}

@Singleton @Provides
QNetworkFactory provideQNetworkFactory(Scenario scenario, EventsManager eventsManager) {
ConfigurableQNetworkFactory qNetworkFactory = new ConfigurableQNetworkFactory(eventsManager, scenario) ;
qNetworkFactory.setLinkSpeedCalculator(new LinkSpeedCalculator(){
LinkSpeedCalculator delegate = new DefaultLinkSpeedCalculator() ;
@Override public double getMaximumVelocity(QVehicle vehicle, Link link, double time) {
if ( vehicle.getVehicle().getType().getId().equals( Id.create("bicycle", VehicleType.class) ) ) {
// return vehicle.getMaximumVelocity(); // return the same as vehicleType.getMaximumVelocity()
// return vehicle.getVehicle().getType().getMaximumVelocity();
return BicycleUtils.getSpeed("bicycle");
} else {
return delegate.getMaximumVelocity(vehicle, link, time) ;
}
}
});
return qNetworkFactory;
}

public void setConsiderMotorizedInteraction(boolean considerMotorizedInteraction) {
this.considerMotorizedInteraction = considerMotorizedInteraction;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* See also COPYING, LICENSE and WARRANTY file *
* *
* *********************************************************************** */
package org.matsim.contrib.bicycle.run;
package org.matsim.contrib.bicycle;

import java.util.HashSet;
import java.util.Set;
Expand Down
Loading

0 comments on commit d4fd09c

Please sign in to comment.