MATSIM
QLinkImpl.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * QueueLink.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2007 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 
21 package org.matsim.core.mobsim.qsim.qnetsimengine;
22 
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.List;
26 import java.util.Objects;
27 
28 import org.apache.logging.log4j.LogManager;
29 import org.apache.logging.log4j.Logger;
30 import org.matsim.api.core.v01.Id;
44 import org.matsim.vehicles.Vehicle;
47 
56 public final class QLinkImpl extends AbstractQLink implements SignalizeableItem {
57  private final static Logger log = LogManager.getLogger(QLinkImpl.class);
58 
59  public static final class Builder {
65 
66  Builder(NetsimEngineContext context, NetsimInternalInterface netsimEngine2) {
67  this.context = context ;
68  this.netsimEngine = netsimEngine2;
69  }
70  final void setLaneFactory( LaneFactory laneFactory ) {
71  this.laneFactory = laneFactory ;
72  }
73 
74  public void setLinkSpeedCalculator(LinkSpeedCalculator linkSpeedCalculator) {
75  this.linkSpeedCalculator = linkSpeedCalculator;
76  }
77 
78  public void setVehicleHandler(VehicleHandler vehicleHandler) {
79  this.vehicleHandler = vehicleHandler;
80  }
81 
82  QLinkImpl build( Link link, QNodeI toNode ) {
83  if ( laneFactory == null ) {
84  laneFactory = new QueueWithBuffer.Builder( context ) ;
85  }
86  Objects.requireNonNull( linkSpeedCalculator );
87  return new QLinkImpl( link, toNode, laneFactory, context, netsimEngine, linkSpeedCalculator, vehicleHandler) ;
88  }
89  }
90 
91  public interface LaneFactory {
92 
98  public QLaneI createLane(AbstractQLink qLinkImpl);
99 
100  }
101 
102  private final VisData visdata;
103 
104  private final QLaneI qlane;
105 
107 
108  private QLinkImpl(final Link link2, final QNodeI toNode, final LaneFactory roadFactory, NetsimEngineContext context,
110  super(link2, toNode, context, netsimEngine, linkSpeedCalculator, vehicleHandler) ;
111  this.context = context ;
112  // The next line must must by contract stay within the constructor,
113  // so that the caller can use references to the created roads to wire them together,
114  // if it must.
115  this.qlane = roadFactory.createLane(this);
116  this.visdata = this.new VisDataImpl() ; // instantiating this here and not earlier so we can cache some things
117  super.setTransitQLink( new TransitQLink(this.qlane) ) ;
118  }
119 
120  @Override
121  public void clearVehicles() {
122  super.clearVehicles();
123  qlane.clearVehicles();
124  }
125 
126  @Override
127  public boolean doSimStep() {
128  double now = context.getSimTimer().getTimeOfDay() ;
129  qlane.initBeforeSimStep();
130 
131  if ( context.qsimConfig.isInsertingWaitingVehiclesBeforeDrivingVehicles() ) {
132  this.moveWaitToRoad();
133  this.getTransitQLink().handleTransitVehiclesInStopQueue(now);
134  qlane.doSimStep();
135  } else {
136  this.getTransitQLink().handleTransitVehiclesInStopQueue(now);
137  qlane.doSimStep();
138  this.moveWaitToRoad();
139  }
140  this.setActive(this.checkForActivity());
141  return isActive();
142  // yy seems to me that for symmetry there should be something like
143  // netElementActivationRegistry.registerLinkAsActive(this);
144  // and may be a qlink.deactivateLink(...) around it (analogous to qlink.activateLink).
145  // That is, do NOT pass the deactivation of the link rather implicitly via returning a false here.
146  // kai, mar'16
147  }
148 
149 
153  private void moveWaitToRoad() {
154  while (!getWaitingList().isEmpty()) {
155  if (!qlane.isAcceptingFromWait(this.getWaitingList().peek())) {
156  return;
157  }
158  QVehicle veh = this.getWaitingList().poll();
159 
160  double now = context.getSimTimer().getTimeOfDay() ;
161  context.getEventsManager().processEvent(
162  new VehicleEntersTrafficEvent(now, veh.getDriver().getId(), this.getLink().getId(), veh.getId(), veh.getDriver().getMode(), 1.0));
163 
164  if ( this.getTransitQLink().addTransitToStopQueue(now, veh, this.getLink().getId()) ) {
165  continue ;
166  }
167 
169  // If the driver wants to stop (again) on this link, give them a special treatment.
170  // addFromWait doesn't work here, because after that, they cannot stop anymore.
172  continue;
173  }
174 
175  qlane.addFromWait(veh);
176  }
177  }
178 
179  @Override
180  public boolean isNotOfferingVehicle() {
181  return qlane.isNotOfferingVehicle();
182  }
183 
184  @Override public void recalcTimeVariantAttributes() {
185  double now = context.getSimTimer().getTimeOfDay() ;
186  qlane.changeUnscaledFlowCapacityPerSecond( this.getLink().getFlowCapacityPerSec(now ) );
187  qlane.changeEffectiveNumberOfLanes(this.getLink().getNumberOfLanes(now));
188 
189  // qlane.changeSpeedMetersPerSecond( getLink().getFreespeed(now) ) ; flowCap & nLanes are "push", freeSpeed is
190  //"pull". This is not completely honest w.r.t. freeSpeed consequences to the fdiag, but also wasn't correctly
191  //thought through/implemented when I found it. kai, feb'18
192 
194  }
195 
196  @Override
197  public QVehicle getVehicle(Id<Vehicle> vehicleId) {
198  QVehicle ret = super.getVehicle(vehicleId);
199  if (ret != null) {
200  return ret;
201  }
202  for (QVehicle veh : this.getWaitingList()) {
203  if (veh.getId().equals(vehicleId))
204  return veh;
205  }
206  return this.qlane.getVehicle( vehicleId ) ;
207  }
208 
209  @Override public Collection<MobsimVehicle> getAllNonParkedVehicles(){
210  Collection<MobsimVehicle> vehicles = new ArrayList<>();
211  vehicles.addAll(this.getTransitQLink().getTransitVehicleStopQueue());
212  vehicles.addAll(this.getWaitingList());
213  vehicles.addAll( qlane.getAllVehicles() ) ;
214  return vehicles;
215  }
216 
220  double getSpaceCap() {
221  return this.qlane.getStorageCapacity();
222  }
223 
232  double getSimulatedFlowCapacityPerTimeStep() {
233  return this.qlane.getSimulatedFlowCapacityPerTimeStep() ;
234  }
235 
236  @Override public VisData getVisData() {
237  return this.visdata;
238  }
239 
240  private boolean checkForActivity() {
241  /*
242  * Leave Link active as long as there are vehicles on the link (ignore
243  * buffer because the buffer gets emptied by nodes and not links) and leave
244  * link active until buffercap has accumulated (so a newly arriving vehicle
245  * is not delayed).
246  */
247  return qlane.isActive() || !this.getWaitingList().isEmpty() || !this.getTransitQLink().getTransitVehicleStopQueue().isEmpty() ;
248  }
249 
250  @Override public void setSignalStateAllTurningMoves(SignalGroupState state) {
251  ((SignalizeableItem) qlane).setSignalStateAllTurningMoves(state);
252  }
253 
254  @Override public void setSignalStateForTurningMove(SignalGroupState state, Id<Link> toLinkId) {
255  ((SignalizeableItem) qlane).setSignalStateForTurningMove(state, toLinkId);
256  }
257 
258  @Override public void setSignalized(boolean isSignalized) {
259  ((SignalizeableItem) qlane).setSignalized(isSignalized);
260  }
261 
262  @Override
263  public boolean hasGreenForToLink(Id<Link> toLinkId) {
264  return ((SignalizeableItem) qlane).hasGreenForToLink(toLinkId);
265  }
266 
267  @Override
268  public boolean hasGreenForAllToLinks() {
269  return ((SignalizeableItem) qlane).hasGreenForAllToLinks();
270  }
271 
277  class VisDataImpl implements VisData {
278 
279  private VisLaneModelBuilder visModelBuilder = null;
280  private VisLinkWLanes visLink = null;
281 
282  private VisDataImpl() {
283  double nodeOffset = context.qsimConfig.getNodeOffset();
284  if (nodeOffset != 0.0) {
285  nodeOffset = nodeOffset +2.0; // +2.0: eventually we need a bit space for the signal
286  visModelBuilder = new VisLaneModelBuilder();
287  CoordinateTransformation transformation = new IdentityTransformation();
288  visLink = visModelBuilder.createVisLinkLanes(transformation, QLinkImpl.this, nodeOffset, null);
289  visModelBuilder.recalculatePositions(visLink, context.linkWidthCalculator);
290  }
291  }
292 
293  @Override
294  public Collection<AgentSnapshotInfo> addAgentSnapshotInfo( Collection<AgentSnapshotInfo> positions) {
295 // AbstractAgentSnapshotInfoBuilder snapshotInfoBuilder = qnetwork.simEngine.getAgentSnapshotInfoBuilder();
296 
297  QLaneI.VisData roadVisData = getAcceptingQLane().getVisData() ;
298  if (visLink != null) {
299  ((QueueWithBuffer.VisDataImpl)roadVisData).setVisInfo(visLink.getLinkStartCoord(), visLink.getLinkEndCoord()) ;
300  // yyyy not so great but an elegant solution needs more thinking about visualizer structure. kai, jun'13
301  }
302 
303  double now = context.getSimTimer().getTimeOfDay() ;
304  positions = roadVisData.addAgentSnapshotInfo(positions,now) ;
305 
306  int cnt2 = 10 ; // a counter according to which non-moving items can be "spread out" in the visualization
307  // initialize a bit away from the lane
308 
309  // treat vehicles from transit stops
310  cnt2 = context.snapshotInfoBuilder.positionVehiclesFromTransitStop(positions, getLink(), getTransitQLink().getTransitVehicleStopQueue(), cnt2 );
311 
312  // treat vehicles from waiting list:
313  cnt2 = context.snapshotInfoBuilder.positionVehiclesFromWaitingList(positions, QLinkImpl.this.getLink(), cnt2,
314  QLinkImpl.this.getWaitingList());
315 
316  cnt2 = context.snapshotInfoBuilder.positionAgentsInActivities(positions, QLinkImpl.this.getLink(),
317  QLinkImpl.this.getAdditionalAgentsOnLink(), cnt2);
318 
319  return positions;
320  }
321 
322  }
323 
324  @Override
325  public List<QLaneI> getOfferingQLanes() {
326  List<QLaneI> list = new ArrayList<>() ;
327  list.add( this.qlane ) ;
328  return list ;
329  }
330  @Override
332  return qlane ;
333  }
334 
335 }
QVehicle getVehicle(final Id< Vehicle > vehicleId)
void addTransitSlightlyUpstreamOfStop(final QVehicle veh)
void changeUnscaledFlowCapacityPerSecond(final double val)
Collection< MobsimVehicle > getAllVehicles()
VisLinkWLanes createVisLinkLanes(CoordinateTransformation transform, VisLink link, double nodeOffsetMeter, List< ModelLane > lanes)
void recalculatePositions(VisLinkWLanes linkData, SnapshotLinkWidthCalculator linkWidthCalculator)