SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
od2trips_main.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // Main for OD2TRIPS
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
13 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #ifdef HAVE_VERSION_H
35 #include <version.h>
36 #endif
37 
38 #include <iostream>
39 #include <algorithm>
40 #include <math.h>
41 #include <cstdlib>
42 #include <string>
43 #include <xercesc/parsers/SAXParser.hpp>
44 #include <xercesc/sax2/SAX2XMLReader.hpp>
45 #include <utils/options/Option.h>
52 #include <utils/common/ToString.h>
53 #include <utils/xml/XMLSubSys.h>
57 #include <od2trips/ODMatrix.h>
59 #include <utils/common/SUMOTime.h>
65 
66 #ifdef CHECK_MEMORY_LEAKS
67 #include <foreign/nvwa/debug_new.h>
68 #endif // CHECK_MEMORY_LEAKS
69 
70 
71 // ===========================================================================
72 // functions
73 // ===========================================================================
74 void
77  oc.addCallExample("-c <CONFIGURATION>", "run with configuration file");
78 
79  // insert options sub-topics
80  SystemFrame::addConfigurationOptions(oc); // fill this subtopic, too
81  oc.addOptionSubTopic("Input");
82  oc.addOptionSubTopic("Output");
83  oc.addOptionSubTopic("Time");
84  oc.addOptionSubTopic("Processing");
85  oc.addOptionSubTopic("Defaults");
86  SystemFrame::addReportOptions(oc); // fill this subtopic, too
87 
88 
89  // register the file input options
90  oc.doRegister("net-file", 'n', new Option_FileName());
91  oc.addSynonyme("net-file", "net");
92  oc.addDescription("net-file", "Input", "Loads network (districts) from FILE");
93 
94  oc.doRegister("od-matrix-files", 'd', new Option_FileName());
95  oc.addSynonyme("od-matrix-files", "od-files");
96  oc.addSynonyme("od-matrix-files", "od");
97  oc.addDescription("od-matrix-files", "Input", "Loads O/D-files from FILE(s)");
98 
99 
100  // register the file output options
101  oc.doRegister("output-file", 'o', new Option_FileName());
102  oc.addSynonyme("output-file", "output", true);
103  oc.addDescription("output-file", "Output", "Writes trip definitions into FILE");
104 
105  oc.doRegister("ignore-vehicle-type", new Option_Bool(false));
106  oc.addSynonyme("ignore-vehicle-type", "no-vtype", true);
107  oc.addDescription("ignore-vehicle-type", "Output", "Does not save vtype information");
108 
109 
110  // register the time settings
111  oc.doRegister("begin", 'b', new Option_String("0", "TIME"));
112  oc.addDescription("begin", "Time", "Defines the begin time; Previous trips will be discarded");
113 
114  oc.doRegister("end", 'e', new Option_String(SUMOTIME_MAXSTRING, "TIME"));
115  oc.addDescription("end", "Time", "Defines the end time; Later trips will be discarded; Defaults to the maximum time that SUMO can represent");
116 
117 
118  // register the data processing options
119  oc.doRegister("scale", 's', new Option_Float(1));
120  oc.addDescription("scale", "Processing", "Scales the loaded flows by FLOAT");
121 
122  oc.doRegister("spread.uniform", new Option_Bool(false));
123  oc.addDescription("spread.uniform", "Processing", "Spreads trips uniformly over each time period");
124 
125  oc.doRegister("vtype", new Option_String(""));
126  oc.addDescription("vtype", "Processing", "Defines the name of the vehicle type to use");
127 
128  oc.doRegister("prefix", new Option_String(""));
129  oc.addDescription("prefix", "Processing", "Defines the prefix for vehicle names");
130 
131  oc.doRegister("timeline", new Option_String());
132  oc.addDescription("timeline", "Processing", "Uses STR as a timeline definition");
133 
134  oc.doRegister("timeline.day-in-hours", new Option_Bool(false));
135  oc.addDescription("timeline.day-in-hours", "Processing", "Uses STR as a 24h-timeline definition");
136 
137  oc.doRegister("dismiss-loading-errors", new Option_Bool(false)); // !!! describe, document
138  oc.addDescription("dismiss-loading-errors", "Processing", "Continue on broken input");
139 
140  oc.doRegister("no-step-log", new Option_Bool(false));
141  oc.addDescription("no-step-log", "Processing", "Disable console output of current time step");
142 
143 
144  // register defaults options
145  oc.doRegister("departlane", new Option_String("free"));
146  oc.addDescription("departlane", "Defaults", "Assigns a default depart lane");
147 
148  oc.doRegister("departpos", new Option_String());
149  oc.addDescription("departpos", "Defaults", "Assigns a default depart position");
150 
151  oc.doRegister("departspeed", new Option_String("max"));
152  oc.addDescription("departspeed", "Defaults", "Assigns a default depart speed");
153 
154  oc.doRegister("arrivallane", new Option_String());
155  oc.addDescription("arrivallane", "Defaults", "Assigns a default arrival lane");
156 
157  oc.doRegister("arrivalpos", new Option_String());
158  oc.addDescription("arrivalpos", "Defaults", "Assigns a default arrival position");
159 
160  oc.doRegister("arrivalspeed", new Option_String());
161  oc.addDescription("arrivalspeed", "Defaults", "Assigns a default arrival speed");
162 
163  // add rand options
165 }
166 
167 
169 parseTimeLine(const std::vector<std::string>& def, bool timelineDayInHours) {
170  bool interpolating = !timelineDayInHours;
171  PositionVector points;
172  SUMOReal prob = 0;
173  if (timelineDayInHours) {
174  if (def.size() != 24) {
175  throw ProcessError("Assuming 24 entries for a day timeline, but got " + toString(def.size()) + ".");
176  }
177  for (int chour = 0; chour < 24; ++chour) {
178  prob = TplConvert::_2SUMOReal(def[chour].c_str());
179  points.push_back(Position((SUMOReal)(chour * 3600), prob));
180  }
181  points.push_back(Position((SUMOReal)(24 * 3600), prob));
182  } else {
183  size_t i = 0;
184  while (i < def.size()) {
185  StringTokenizer st2(def[i++], ":");
186  if (st2.size() != 2) {
187  throw ProcessError("Broken time line definition: missing a value in '" + def[i - 1] + "'.");
188  }
189  int time = TplConvert::_2int(st2.next().c_str());
190  prob = TplConvert::_2SUMOReal(st2.next().c_str());
191  points.push_back(Position((SUMOReal) time, prob));
192  }
193  }
194  return Distribution_Points("N/A", points, interpolating);
195 }
196 
197 
198 bool
201  bool ok = true;
202  if (!oc.isSet("net-file")) {
203  WRITE_ERROR("No net input file (-n) specified.");
204  ok = false;
205  }
206  if (!oc.isSet("od-matrix-files")) {
207  WRITE_ERROR("No input specified.");
208  ok = false;
209  }
210  if (!oc.isSet("output-file")) {
211  WRITE_ERROR("No trip table output file (-o) specified.");
212  ok = false;
213  }
214  //
216  std::string error;
217  if (oc.isSet("departlane") && !SUMOVehicleParameter::parseDepartLane(oc.getString("departlane"), "option", "departlane", p.departLane, p.departLaneProcedure, error)) {
218  WRITE_ERROR(error);
219  ok = false;
220  }
221  if (oc.isSet("departpos") && !SUMOVehicleParameter::parseDepartPos(oc.getString("departpos"), "option", "departpos", p.departPos, p.departPosProcedure, error)) {
222  WRITE_ERROR(error);
223  ok = false;
224  }
225  if (oc.isSet("departspeed") && !SUMOVehicleParameter::parseDepartSpeed(oc.getString("departspeed"), "option", "departspeed", p.departSpeed, p.departSpeedProcedure, error)) {
226  WRITE_ERROR(error);
227  ok = false;
228  }
229  if (oc.isSet("arrivallane") && !SUMOVehicleParameter::parseArrivalLane(oc.getString("arrivallane"), "option", "arrivallane", p.arrivalLane, p.arrivalLaneProcedure, error)) {
230  WRITE_ERROR(error);
231  ok = false;
232  }
233  if (oc.isSet("arrivalpos") && !SUMOVehicleParameter::parseArrivalPos(oc.getString("arrivalpos"), "option", "arrivalpos", p.arrivalPos, p.arrivalPosProcedure, error)) {
234  WRITE_ERROR(error);
235  ok = false;
236  }
237  if (oc.isSet("arrivalspeed") && !SUMOVehicleParameter::parseArrivalSpeed(oc.getString("arrivalspeed"), "option", "arrivalspeed", p.arrivalSpeed, p.arrivalSpeedProcedure, error)) {
238  WRITE_ERROR(error);
239  ok = false;
240  }
241  return ok;
242 }
243 
244 
245 void
247  // check whether the user gave a net filename
248  if (!oc.isSet("net-file")) {
249  WRITE_ERROR("You must supply a network ('-n').");
250  return;
251  }
252  // get the file name and set it
253  std::string file = oc.getString("net-file");
254  if (!FileHelpers::exists(file)) {
255  throw ProcessError("Could not find network '" + file + "' to load.");
256  }
257  PROGRESS_BEGIN_MESSAGE("Loading districts from '" + file + "'");
258  // build the xml-parser and handler
259  ODDistrictHandler handler(districts, file);
260  if (!XMLSubSys::runParser(handler, file)) {
262  } else {
264  }
265 }
266 
267 
268 std::string
270  std::string line;
271  do {
272  line = lr.readLine();
273  if (line[0] != '*') {
274  return StringUtils::prune(line);
275  }
276  } while (lr.good() && lr.hasMore());
277  throw ProcessError();
278 }
279 
280 
281 SUMOTime
282 parseSingleTime(const std::string& time) {
283  if (time.find('.') == std::string::npos) {
284  throw OutOfBoundsException();
285  }
286  std::string hours = time.substr(0, time.find('.'));
287  std::string minutes = time.substr(time.find('.') + 1);
288  return TIME2STEPS(TplConvert::_2int(hours.c_str()) * 3600 + TplConvert::_2int(minutes.c_str()) * 60);
289 }
290 
291 
292 std::pair<SUMOTime, SUMOTime>
294  std::string line = getNextNonCommentLine(lr);
295  try {
297  SUMOTime begin = parseSingleTime(st.next());
298  SUMOTime end = parseSingleTime(st.next());
299  if (begin >= end) {
300  throw ProcessError("Begin time is larger than end time.");
301  }
302  return std::make_pair(begin, end);
303  } catch (OutOfBoundsException&) {
304  throw ProcessError("Broken period definition '" + line + "'.");
305  } catch (NumberFormatException&) {
306  throw ProcessError("Broken period definition '" + line + "'.");
307  }
308 }
309 
310 
311 SUMOReal
313  std::string line = getNextNonCommentLine(lr);
314  SUMOReal factor = -1;
315  try {
316  factor = TplConvert::_2SUMOReal(line.c_str()) * scale;
317  } catch (NumberFormatException&) {
318  throw ProcessError("Broken factor: '" + line + "'.");
319  }
320  return factor;
321 }
322 
323 
324 
325 void
326 readV(LineReader& lr, ODMatrix& into, SUMOReal scale,
327  std::string vehType, bool matrixHasVehType) {
328  PROGRESS_BEGIN_MESSAGE("Reading matrix '" + lr.getFileName() + "' stored as VMR");
329  // parse first defs
330  std::string line;
331  if (matrixHasVehType) {
332  line = getNextNonCommentLine(lr);
333  if (vehType == "") {
334  vehType = StringUtils::prune(line);
335  }
336  }
337 
338  // parse time
339  std::pair<SUMOTime, SUMOTime> times = readTime(lr);
340  SUMOTime begin = times.first;
341  SUMOTime end = times.second;
342 
343  // factor
344  SUMOReal factor = readFactor(lr, scale);
345 
346  // districts
347  line = getNextNonCommentLine(lr);
348  int districtNo = TplConvert::_2int(StringUtils::prune(line).c_str());
349  // parse district names (normally ints)
350  std::vector<std::string> names;
351  do {
352  line = getNextNonCommentLine(lr);
354  while (st2.hasNext()) {
355  names.push_back(st2.next());
356  }
357  } while ((int) names.size() != districtNo);
358 
359  // parse the cells
360  for (std::vector<std::string>::iterator si = names.begin(); si != names.end(); ++si) {
361  std::vector<std::string>::iterator di = names.begin();
362  //
363  do {
364  line = getNextNonCommentLine(lr);
365  if (line.length() == 0) {
366  continue;
367  }
368  try {
370  while (st2.hasNext()) {
371  assert(di != names.end());
372  SUMOReal vehNumber = TplConvert::_2SUMOReal(st2.next().c_str()) * factor;
373  if (vehNumber != 0) {
374  into.add(vehNumber, begin, end, *si, *di, vehType);
375  }
376  if (di == names.end()) {
377  throw ProcessError("More entries than districts found.");
378  }
379  ++di;
380  }
381  } catch (NumberFormatException&) {
382  throw ProcessError("Not numeric vehicle number in line '" + line + "'.");
383  }
384  if (!lr.hasMore()) {
385  break;
386  }
387  } while (di != names.end());
388  }
390 }
391 
392 
393 void
394 readO(LineReader& lr, ODMatrix& into, SUMOReal scale,
395  std::string vehType, bool matrixHasVehType) {
396  PROGRESS_BEGIN_MESSAGE("Reading matrix '" + lr.getFileName() + "' stored as OR");
397  // parse first defs
398  std::string line;
399  if (matrixHasVehType) {
400  line = getNextNonCommentLine(lr);
401  int type = TplConvert::_2int(StringUtils::prune(line).c_str());
402  if (vehType == "") {
403  vehType = toString(type);
404  }
405  }
406 
407  // parse time
408  std::pair<SUMOTime, SUMOTime> times = readTime(lr);
409  SUMOTime begin = times.first;
410  SUMOTime end = times.second;
411 
412  // factor
413  SUMOReal factor = readFactor(lr, scale);
414 
415  // parse the cells
416  while (lr.hasMore()) {
417  line = getNextNonCommentLine(lr);
418  if (line.length() == 0) {
419  continue;
420  }
422  if (st2.size() == 0) {
423  continue;
424  }
425  try {
426  std::string sourceD = st2.next();
427  std::string destD = st2.next();
428  SUMOReal vehNumber = TplConvert::_2SUMOReal(st2.next().c_str()) * factor;
429  if (vehNumber != 0) {
430  into.add(vehNumber, begin, end, sourceD, destD, vehType);
431  }
432  } catch (OutOfBoundsException&) {
433  throw ProcessError("Missing at least one information in line '" + line + "'.");
434  } catch (NumberFormatException&) {
435  throw ProcessError("Not numeric vehicle number in line '" + line + "'.");
436  }
437  }
439 }
440 
441 
442 void
444  std::vector<std::string> files = oc.getStringVector("od-files");
445  // check
446  if (files.size() == 0) {
447  throw ProcessError("No files to parse are given.");
448  }
449  // parse
450  for (std::vector<std::string>::iterator i = files.begin(); i != files.end(); ++i) {
451  LineReader lr(*i);
452  if (!lr.good()) {
453  throw ProcessError("Could not open '" + (*i) + "'.");
454  }
455  std::string type = lr.readLine();
456  // get the type only
457  if (type.find(';') != std::string::npos) {
458  type = type.substr(0, type.find(';'));
459  }
460  // parse type-dependant
461  if (type.length() > 1 && type[1] == 'V') {
462  // process ptv's 'V'-matrices
463  if (type.find('N') != std::string::npos) {
464  throw ProcessError("'" + *i + "' does not contain the needed information about the time described.");
465  }
466  readV(lr, into, oc.getFloat("scale"), oc.getString("vtype"), type.find('M') != std::string::npos);
467  } else if (type.length() > 1 && type[1] == 'O') {
468  // process ptv's 'O'-matrices
469  if (type.find('N') != std::string::npos) {
470  throw ProcessError("'" + *i + "' does not contain the needed information about the time described.");
471  }
472  readO(lr, into, oc.getFloat("scale"), oc.getString("vtype"), type.find('M') != std::string::npos);
473  } else {
474  throw ProcessError("'" + *i + "' uses an unknown matrix type '" + type + "'.");
475  }
476  }
477 }
478 
479 
480 /* -------------------------------------------------------------------------
481  * main
482  * ----------------------------------------------------------------------- */
483 int
484 main(int argc, char** argv) {
486  // give some application descriptions
487  oc.setApplicationDescription("Importer of O/D-matrices for the road traffic simulation SUMO.");
488  oc.setApplicationName("od2trips", "SUMO od2trips Version " + (std::string)VERSION_STRING);
489  int ret = 0;
490  try {
491  // initialise subsystems
492  XMLSubSys::init();
493  fillOptions();
494  OptionsIO::getOptions(true, argc, argv);
495  if (oc.processMetaOptions(argc < 2)) {
497  return 0;
498  }
499  XMLSubSys::setValidation(oc.getBool("xml-validation"));
501  if (!checkOptions()) {
502  throw ProcessError();
503  }
505  // load the districts
506  ODDistrictCont districts;
507  loadDistricts(districts, oc);
508  if (districts.size() == 0) {
509  throw ProcessError("No districts loaded...");
510  }
511  // load the matrix
512  ODMatrix matrix(districts);
513  loadMatrix(oc, matrix);
514  if (matrix.getNoLoaded() == 0) {
515  throw ProcessError("No vehicles loaded...");
516  }
517  if (MsgHandler::getErrorInstance()->wasInformed() && !oc.getBool("dismiss-loading-errors")) {
518  throw ProcessError("Loading failed...");
519  }
520  WRITE_MESSAGE(toString(matrix.getNoLoaded()) + " vehicles loaded.");
521  // apply a curve if wished
522  if (oc.isSet("timeline")) {
523  matrix.applyCurve(parseTimeLine(oc.getStringVector("timeline"), oc.getBool("timeline.day-in-hours")));
524  }
525  // write
526  if (!OutputDevice::createDeviceByOption("output-file", "trips")) {
527  throw ProcessError("No output name is given.");
528  }
529  OutputDevice& dev = OutputDevice::getDeviceByOption("output-file");
530  matrix.write(string2time(oc.getString("begin")), string2time(oc.getString("end")),
531  dev, oc.getBool("spread.uniform"), oc.getBool("ignore-vehicle-type"),
532  oc.getString("prefix"), !oc.getBool("no-step-log"));
533  WRITE_MESSAGE(toString(matrix.getNoDiscarded()) + " vehicles discarded.");
534  WRITE_MESSAGE(toString(matrix.getNoWritten()) + " vehicles written.");
535  } catch (const ProcessError& e) {
536  if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
537  WRITE_ERROR(e.what());
538  }
539  MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
540  ret = 1;
541 #ifndef _DEBUG
542  } catch (const std::exception& e) {
543  if (std::string(e.what()) != std::string("")) {
544  WRITE_ERROR(e.what());
545  }
546  MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
547  ret = 1;
548  } catch (...) {
549  MsgHandler::getErrorInstance()->inform("Quitting (on unknown error).", false);
550  ret = 1;
551 #endif
552  }
554  if (ret == 0) {
555  std::cout << "Success." << std::endl;
556  }
557  return ret;
558 }
559 
560 
561 
562 /****************************************************************************/
563