Package org.movsim.simulator.roadnetwork

Source Code of org.movsim.simulator.roadnetwork.TrafficSourceMacro

/*
* Copyright (C) 2010, 2011, 2012 by Arne Kesting, Martin Treiber, Ralph Germ, Martin Budden
*                                   <movsim.org@gmail.com>
* -----------------------------------------------------------------------------------------
*
* This file is part of
*
* MovSim - the multi-model open-source vehicular-traffic simulator.
*
* MovSim 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 3 of the License, or
* (at your option) any later version.
*
* MovSim is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MovSim. If not, see <http://www.gnu.org/licenses/>
* or <http://www.movsim.org>.
*
* -----------------------------------------------------------------------------------------
*/
package org.movsim.simulator.roadnetwork;

import org.movsim.simulator.vehicles.TestVehicle;
import org.movsim.simulator.vehicles.TrafficCompositionGenerator;
import org.movsim.simulator.vehicles.Vehicle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* The Class TrafficSourceMacro.
*/
public class TrafficSourceMacro extends AbstractTrafficSource {

    /** The Constant LOG. */
    private static final Logger LOG = LoggerFactory.getLogger(TrafficSourceMacro.class);
   
    private final InflowTimeSeries inflowTimeSeries;

    private TestVehicle testVehicle;

    /**
     * Instantiates a new upstream boundary .
     *
     * @param vehGenerator
     *            the vehicle generator
     */
    public TrafficSourceMacro(TrafficCompositionGenerator vehGenerator, RoadSegment roadSegment,
            InflowTimeSeries inflowTimeSeries) {
        super(vehGenerator, roadSegment);
        this.inflowTimeSeries = inflowTimeSeries;
    }

    @Override
    public void timeStep(double dt, double simulationTime, long iterationCount) {
        final double totalInflow = getTotalInflow(simulationTime);
        nWait += totalInflow * dt;
       
        calcApproximateInflow(dt);
       
        if (nWait >= 1.0) {
            if (testVehicle == null) {
                testVehicle = vehGenerator.getTestVehicle();
            }
            // try to insert new vehicle at inflow, iterate periodically over n lanes
            int iLane = laneEnterLast;
            for (int i = 0, N = roadSegment.laneCount(); i < N; i++) {
                iLane = getNewCyclicLaneForEntering(iLane);
                final LaneSegment laneSegment = roadSegment.laneSegment(iLane);
                // laneIndex index is identical to vehicle's lanenumber
                // type of new vehicle
                final boolean isEntered = tryEnteringNewVehicle(testVehicle, laneSegment, simulationTime, totalInflow);
                if (isEntered) {
                    testVehicle = null;
                    nWait--;
                    incrementInflowCount(1);
                    recordData(simulationTime, totalInflow);
                    return; // only one insert per simulation update
                }
            }
        }
    }

    /**
     * <p>
     * Try entering new vehicle.
     * </p>
     *
     * <p>
     * If the inflow is near capacity, it is crucial to avoid initial perturbations as much as possible. Otherwise, one
     * would activate an "inflow bottleneck", and less vehicles can be entered as one would like to. The crux is that
     * vehicles can be introduced only at times given by the simulation time step which is generally incommensurate with
     * the inverse of the inflow. For example, if the simulation time step is 0.4s, capacity is 2400 veh/h, and the
     * prescribed inflow is 2260 veh/h or one vehicle every 1.59s, you insert one vehicle every 1.6s, most of the time.
     * However, at some instances, two vehicles are inserted at time headway of 1.2s corresponding macroscopically to
     * 3000 veh/h, far above capacity. Typical time gaps for this situation are 1.2s most of the time but 0.8s
     * occasionally. This introduces a perturbation which may "activate" the "inflow bottleneck", unless a flow of 2260
     * veh/h is absolutely stable which is not always the case. Since the time of insertion cannot be changed, one can
     * homogenize the inflow by allowing the insertion point to vary by a maximum of one vehicle-vehicle distance.
     * </p>
     *
     * @param laneSegment
     * @param time
     *            the time
     * @param qBC
     *            the q bc
     * @return true, if successful
     */
    private boolean tryEnteringNewVehicle(TestVehicle testVehicle, LaneSegment laneSegment, double time, double qBC) {

        final Vehicle leader = laneSegment.rearVehicle();

        // (1) empty road
        if (leader == null) {
            enterVehicleOnEmptyRoad(laneSegment, time, testVehicle);
            return true;
        }
        // (2) check if gap to leader is sufficiently large origin of road section is assumed to be zero
        final double netGapToLeader = leader.getRearPosition();
        final double gapAtQMax = 1. / testVehicle.getRhoQMax();

        // minimal distance set to 80% of 1/rho at flow maximum in fundamental diagram
        double minRequiredGap = 0.8 * gapAtQMax;
        if (testVehicle.getLongitudinalModel().isCA()) {
            minRequiredGap = leader.getSpeed();
        }
        if (netGapToLeader > minRequiredGap) {
            enterVehicle(laneSegment, time, minRequiredGap, testVehicle, leader);
            return true;
        }
        // no entering possible
        return false;
    }

    /**
     * Enter vehicle on empty road.
     *
     * @param laneSegment
     * @param time
     *            the time
     * @param vehPrototype
     *            the vehicle prototype
     */
    private void enterVehicleOnEmptyRoad(LaneSegment laneSegment, double time, TestVehicle testVehicle) {
        final double xEnter = 0;
        final double vEnter = inflowTimeSeries.getSpeed(time);
        addVehicle(laneSegment, testVehicle, xEnter, vEnter);
        LOG.debug("add vehicle from upstream boundary to empty road: xEnter={}, vEnter={}", xEnter, vEnter);
    }

    /**
     * Enter vehicle.
     *
     * @param laneSegment
     * @param time
     * @param sFreeMin
     * @param vehPrototype
     * @param leader
     */
    private void enterVehicle(LaneSegment laneSegment, double time, double sFreeMin, TestVehicle testVehicle,
            Vehicle leader) {

        final double speedDefault = inflowTimeSeries.getSpeed(time);

        final double sFree = leader.getMidPosition() - leader.getLength();
        final double xLast = leader.getMidPosition();
        final double vLast = leader.getSpeed();
        final double aLast = leader.getAcc();

        final double vEnterTest = Math.min(speedDefault, 1.5 * vLast);
        final double lengthLast = leader.getLength();

        final double qBC = inflowTimeSeries.getFlowPerLane(time);
        final double xEnter = Math.min(vEnterTest * nWait / Math.max(qBC, 0.001), xLast - sFreeMin - lengthLast);
        final double rhoEnter = 1. / (xLast - xEnter);
        final double vMaxEq = testVehicle.getEquilibriumSpeed(0.5 * rhoEnter);
        final double bMax = 4; // max. kinematic deceleration at boundary
        final double bEff = Math.max(0.1, bMax + aLast);
        final double vMaxKin = vLast + Math.sqrt(2 * sFree * bEff);
        final double vEnter = Math.min(Math.min(vEnterTest, vMaxEq), vMaxKin);

        addVehicle(laneSegment, testVehicle, xEnter, vEnter);
    }

    @Override
    public double getTotalInflow(double time) {
        return inflowTimeSeries.getFlowPerLane(time) * roadSegment.laneCount();
    }

}
TOP

Related Classes of org.movsim.simulator.roadnetwork.TrafficSourceMacro

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.