MATSIM
LanesConsistencyChecker.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * LanesConsistencyChecker
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2009 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 package org.matsim.lanes.data.consistency;
21 
22 import java.util.Arrays;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.Iterator;
26 import java.util.LinkedList;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 
31 import org.apache.logging.log4j.LogManager;
32 import org.apache.logging.log4j.Logger;
33 import org.matsim.api.core.v01.Id;
37 import org.matsim.lanes.Lane;
38 import org.matsim.lanes.Lanes;
40 
41 
47 
48  private static final Logger log = LogManager.getLogger(LanesConsistencyChecker.class);
49  private Network network;
50  private Lanes lanes;
51  private boolean removeMalformed = false;
52 
53  public LanesConsistencyChecker(Network net, Lanes laneDefs) {
54  this.network = net;
55  this.lanes = laneDefs;
56  }
57 
58  public void checkConsistency() {
59  log.info("Checking consistency of lane data...");
60  List<Id<Link>> linksWithMalformedLanes = new LinkedList<>();
61  for (LanesToLinkAssignment l2l : this.lanes.getLanesToLinkAssignments().values()){
62  if (!areLanesOnLinkConsistent(l2l)){
63  linksWithMalformedLanes.add(l2l.getLinkId());
64  }
65  }
66 
67  if (this.removeMalformed){
68  for (Id<Link> linkId : linksWithMalformedLanes) {
69  this.lanes.getLanesToLinkAssignments().remove(linkId);
70  log.info("remove lanes on link " + linkId);
71  }
72  }
73  log.info("checked consistency. Lanes on " + linksWithMalformedLanes.size() + " links have been removed.");
74  }
75 
77  //check if link exists for each assignment of one or more lanes to a link
78  if (!this.network.getLinks().containsKey(l2l.getLinkId())) {
79  log.error("No link found for lanesToLinkAssignment on link Id(linkIdRef): " + l2l.getLinkId());
80  return false;
81  }
82  //check length
83  else {
84  Link link = this.network.getLinks().get(l2l.getLinkId());
85  for (Lane l : l2l.getLanes().values()){
86  if (link.getLength() < l.getStartsAtMeterFromLinkEnd()) {
87  log.error("Link Id " + link.getId() + " is shorter than an assigned lane with id " + l.getId());
88  return false;
89  }
90  }
91  }
92 
93  // sbraun Dec 2020:
94  // If Links are merged via NetworkSimplifier, the new name has to be added to lane file
95  // (signal nodes are excluded from merging therefore the signal file is already fine)
96 
97  Map<Id<Link>,Id<Link>> mergedLinks = new HashMap();
98  for (Id<Link> link : network.getLinks().keySet()){
99  if(link.toString().contains("-")){
100  List<String> origLinks = Arrays.asList(link.toString().split("-"));
101  for (String origlink : origLinks){
102  mergedLinks.put(Id.createLinkId(origlink),link);
103  }
104  }
105  }
106  // Update Lanefile
107  for (Id<Link> link : network.getLinks().keySet()) {
108  if (lanes.getLanesToLinkAssignments().get(link) != null &&
109  lanes.getLanesToLinkAssignments().get(link).getLanes().values() != null) {
110  for (Lane lane : lanes.getLanesToLinkAssignments().get(link).getLanes().values()) {
111  if (lane.getToLinkIds()!=null) {
112  Set<Id<Link>> links2Replace = new HashSet<>();
113  for (Id<Link> toLink : lane.getToLinkIds()) {
114  if (mergedLinks.keySet().contains(toLink)) {
115  Id<Link> merged = mergedLinks.get(toLink);
116 
117  links2Replace.add(merged);
118  }
119  }
120  if (!links2Replace.isEmpty()) {
121  for (Id<Link> temp : links2Replace) {
122  lane.addToLinkId(temp);
123  }
124  if (removeMalformed) {
125  Iterator<Id<Link>> toLinkIdIterator = lane.getToLinkIds().iterator();
126  while (toLinkIdIterator.hasNext()) {
127  Id<Link> toLinkId = toLinkIdIterator.next();
128  if (mergedLinks.keySet().contains(toLinkId)) {
129  toLinkIdIterator.remove();
130  log.info("Replace ToLinks of Lane Id: " + lane.getId() + " on Link Id: " + l2l.getLinkId() +
131  " - Replace ToLink Id: " + toLinkId.toString() + " with " + mergedLinks.get(toLinkId).toString());
132  }
133  }
134  }
135  }
136  }
137  }
138  }
139  }
140 
141 
142  //sbraun Dec 2020
143  // Check a junction where the InLinks have lanes
144  // More precisely: check if every Outlink is reachable (and if not delete all lanes at this junction)
145  // Note: This case should happen rarely and
146  // only when turn restrictions are misinterpreted or the OSM-data was not understood
147 
148  log.info("Check if all OutLinks of junction with lanes is reachable...");
149  Map<Id<Node>,Set<Id<Link>>> junctionNodes = new HashMap<>();
150  //Fill Map with junction nodes and all ToLinks from Lanes
151  for (Id<Link> link : network.getLinks().keySet()) {
152  if (lanes.getLanesToLinkAssignments().get(link) != null &&
153  lanes.getLanesToLinkAssignments().get(link).getLanes().values() != null) {
154  for (Lane lane : lanes.getLanesToLinkAssignments().get(link).getLanes().values()) {
155  if (lane.getToLinkIds() != null) {
156  Id<Node> jn = network.getLinks().get(link).getToNode().getId();
157  if (!junctionNodes.containsKey(jn)){
158  junctionNodes.put(jn,new HashSet<Id<Link>>());
159  }
160  for (Id<Link> toLink :lane.getToLinkIds()){
161  if (!junctionNodes.get(jn).contains(toLink)) junctionNodes.get(jn).add(toLink);
162  }
163  }
164  }
165  }
166  }
167  Set<Id<Node>> checkedJn = new HashSet<Id<Node>>();
168  for (Id<Node> jn : junctionNodes.keySet()){
169  //At a junction if the size of the set filled above equals the number of outLinks everything is fine
170  if (network.getNodes().get(jn).getOutLinks().keySet().size()== junctionNodes.get(jn).size()){
171  checkedJn.add(jn);
172  continue;
173  }
174  //If there is one inLink of that junction which has no Lanes (i.e connects every Outlink) - the junction is fine
175  for (Id<Link>inLink :network.getNodes().get(jn).getInLinks().keySet()){
176  if (!lanes.getLanesToLinkAssignments().containsKey(inLink)){
177  checkedJn.add(jn);
178  break;
179  }
180  }
181  // Identify the not connected OutLink
182  for (Id<Link>outLink :network.getNodes().get(jn).getOutLinks().keySet()){
183  if (!junctionNodes.get(jn).contains(outLink) && !checkedJn.contains(jn)){
184  log.warn("Link "+outLink.toString()+" is not connected to the network - remove lanes from all inLinks of the corresponding junction:");
185  checkedJn.add(jn);
186  for (Id<Link> inLink: network.getNodes().get(jn).getInLinks().keySet()){
187  log.warn("\t\tRemove Lanes on Link "+inLink.toString());
188  lanes.getLanesToLinkAssignments().remove(inLink);
189  }
190  }
191  }
192  }
193 
194 
195 
196 
197 
198 
199 
200  //check toLinks or toLanes specified in the lanes
201  for (Lane lane : l2l.getLanes().values()) {
202  if (lane.getToLaneIds() != null) {
203  Iterator<Id<Lane>> toLaneIdIterator = lane.getToLaneIds().iterator();
204  while (toLaneIdIterator.hasNext()){
205  Id<Lane> toLaneId = toLaneIdIterator.next();
206  if (! l2l.getLanes().containsKey(toLaneId)){
207  log.error("Error: toLane not existing:");
208  log.error(" Lane Id: " + lane.getId() + " on Link Id: " + l2l.getLinkId() +
209  " leads to Lane Id: " + toLaneId + " that is not existing!");
210 // return false; // do not return false because this would remove the whole l2l on this link
211  // delete this toLane from the lane
212  if (this.removeMalformed) {
213  toLaneIdIterator.remove();
214  }
215  }
216  }
217  }
218  //check availability of toLink in network
219  if (lane.getToLinkIds() != null){
220  Iterator<Id<Link>> toLinkIdIterator = lane.getToLinkIds().iterator();
221  while (toLinkIdIterator.hasNext()) {
222  Id<Link> toLinkId = toLinkIdIterator.next();
223  if (! this.network.getLinks().containsKey(toLinkId)){
224  log.error("No link found in network for toLinkId " + toLinkId + " of laneId " + lane.getId() + " of link id " + l2l.getLinkId());
225 // return false; // do not return false because this would remove the whole l2l on this link
226  // delete this toLink from the lane
227  if (this.removeMalformed) {
228  toLinkIdIterator.remove();
229  }
230  } else {
231  Link link = this.network.getLinks().get(l2l.getLinkId());
232  if (! link.getToNode().getOutLinks().containsKey(toLinkId)){
233  log.error("The given toLink " + toLinkId + " is not reachable from lane " + lane.getId() + " on link " + link.getId());
234 // return false; // do not return false because this would remove the whole l2l on this link
235  // delete this toLink from the lane
236  if (this.removeMalformed) {
237  toLinkIdIterator.remove();
238  }
239  }
240  }
241  }
242  }
243  // identify lanes without tolanes and tolinks
244  if ((lane.getToLaneIds() == null || lane.getToLaneIds().isEmpty())
245  && (lane.getToLinkIds() == null || lane.getToLinkIds().isEmpty())) {
246  log.error("The lane " + lane.getId() + " on link " + l2l.getLinkId() + " does not lead to any lane nor link.");
247  return false;
248  }
249  }
250  // identify lanes on links that only have one outlink
251  Link link = this.network.getLinks().get(l2l.getLinkId());
252  if (link.getToNode().getOutLinks().size() <= 1){
253  log.error("The link " + link.getId() + " has lanes but only one outLink.");
254  return false;
255  }
256 
257  // comment this out, because not every out-link of a node has to be reached by every in-link. theresa, aug'17
258 // //second check matching of link's outlinks and lane's toLinks
259 // Link link = this.network.getLinks().get(l2l.getLinkId());
260 // log.info("Link id: " + l2l.getLinkId());
261 // Set<Id<Link>> toLinksFromLanes = new HashSet<>();
262 // for (Lane lane : l2l.getLanes().values()){
263 // if (lane.getToLinkIds() != null){
264 // toLinksFromLanes.addAll(lane.getToLinkIds());
265 // }
266 // }
267 //
268 // for (Link nodeOutLink : link.getToNode().getOutLinks().values()){
269 // log.info("\t\thas outlink: " + nodeOutLink.getId());
270 // if (!toLinksFromLanes.contains(nodeOutLink.getId())){
271 // log.error("Error: Lane Outlink: ");
272 // log.error("\t\tThe lanes of link " + link.getId() + " do not lead to all of the outlinks of the links toNode " + link.getToNode().getId() + " . The outlink " + nodeOutLink.getId()
273 // + " is not reachable from the lanes of this link. ");
274 // for (Lane lane : l2l.getLanes().values()){
275 // log.error("\t\tLane id: " + lane.getId());
276 // if (lane.getToLinkIds() != null){
277 // for (Id<Link> id : lane.getToLinkIds()){
278 // log.error("\t\t\t\thas toLinkId: " + id);
279 // }
280 // }
281 // log.error("End: Lane Outlink Error Message");
282 // }
283 // return false;
284 // }
285 // }
286  return true;
287  }
288 
289  public boolean isRemoveMalformed() {
290  return removeMalformed;
291  }
292 
293  public void setRemoveMalformed(boolean removeMalformed) {
294  this.removeMalformed = removeMalformed;
295  }
296 
297 }
static< T > Id< T > get(int index, final Class< T > type)
Definition: Id.java:112
Map< Id< Node >, ? extends Node > getNodes()
SortedMap< Id< Link >, LanesToLinkAssignment > getLanesToLinkAssignments()
static Id< Link > createLinkId(final long key)
Definition: Id.java:202
Map< Id< Link >, ? extends Link > getLinks()
Map< Id< Link >, ? extends Link > getOutLinks()