SUMO - Simulation of Urban MObility
emissionsDrivingCycle_main.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2013-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
18 // Main for an emissions calculator
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #ifdef _MSC_VER
26 #include <windows_config.h>
27 #else
28 #include <config.h>
29 #endif
30 
31 #ifdef HAVE_VERSION_H
32 #include <version.h>
33 #endif
34 
36 #include <iostream>
37 #include <string>
38 #include <ctime>
40 #include <utils/options/Option.h>
45 #include <utils/common/ToString.h>
46 #include <utils/xml/XMLSubSys.h>
54 #include "TrajectoriesHandler.h"
55 
56 
57 // ===========================================================================
58 // functions
59 // ===========================================================================
60 
61 
62 /* -------------------------------------------------------------------------
63  * main
64  * ----------------------------------------------------------------------- */
65 int
66 main(int argc, char** argv) {
67  // build options
69  // give some application descriptions
70  oc.setApplicationDescription("Computes emissions by driving a time line.");
71  oc.setApplicationName("emissionsDrivingCycle", "SUMO emissionsDrivingCycle Version " VERSION_STRING);
72  // add options
73 
75  oc.addOptionSubTopic("Input");
76  oc.doRegister("timeline-file", 't', new Option_FileName());
77  oc.addSynonyme("timeline", "timeline-file");
78  oc.addDescription("timeline-file", "Input", "Defines the file to read the driving cycle from.");
79 
80  oc.doRegister("timeline-file.skip", new Option_Integer(0));
81  oc.addSynonyme("timeline.skip", "timeline-file.skip");
82  oc.addDescription("timeline-file.skip", "Input", "Skips the firs NUM lines.");
83 
84  oc.doRegister("timeline-file.separator", new Option_String(";"));
85  oc.addSynonyme("timeline.separator", "timeline-file.separator");
86  oc.addDescription("timeline-file.separator", "Input", "Defines the entry separator.");
87 
88  oc.doRegister("netstate-file", 'n', new Option_FileName());
89  oc.addSynonyme("netstate", "netstate-file");
90  oc.addSynonyme("amitran", "netstate-file");
91  oc.addDescription("netstate-file", "Input", "Defines the netstate, route and trajectory files to read the driving cycles from.");
92 
93  oc.doRegister("emission-class", 'e', new Option_String("unknown"));
94  oc.addDescription("emission-class", "Input", "Defines for which emission class the emissions shall be generated. ");
95 
96 
97  oc.addOptionSubTopic("Processing");
98  oc.doRegister("compute-a", 'a', new Option_Bool(false));
99  oc.addDescription("compute-a", "Processing", "If set, the acceleration is computed instead of being read from the file. ");
100 
101  oc.doRegister("compute-a.forward", new Option_Bool(false));
102  oc.addDescription("compute-a.forward", "Processing", "If set, the acceleration for time t is computed from v(t+1) - v(t) instead of v(t) - v(t-1). ");
103 
104  oc.doRegister("compute-a.zero-correction", new Option_Bool(false));
105  oc.addDescription("compute-a.zero-correction", "Processing", "If set, the acceleration for time t is set to 0 if the speed is 0. ");
106 
107  oc.doRegister("skip-first", 's', new Option_Bool(false));
108  oc.addDescription("skip-first", "Processing", "If set, the first line of the read file is skipped.");
109 
110  oc.doRegister("kmh", new Option_Bool(false));
111  oc.addDescription("kmh", "Processing", "If set, the given speed is interpreted as being given in km/h.");
112 
113  oc.doRegister("have-slope", new Option_Bool(false));
114  oc.addDescription("have-slope", "Processing", "If set, the fourth column is read and used as slope (in deg).");
115 
116  oc.doRegister("slope", new Option_Float(0));
117  oc.addDescription("slope", "Processing", "Sets a global slope (in deg) that is used if the file does not contain slope information.");
118 
119  oc.addOptionSubTopic("Output");
120  oc.doRegister("output-file", 'o', new Option_String());
121  oc.addSynonyme("output", "output-file");
122  oc.addDescription("output", "Output", "Defines the file to write the emission cycle results into. ");
123 
124  oc.doRegister("emission-output", new Option_FileName());
125  oc.addDescription("emission-output", "Output", "Save the emission values of each vehicle in XML");
126 
127  oc.doRegister("sum-output", new Option_FileName());
128  oc.addSynonyme("sum", "sum-output");
129  oc.addDescription("sum-output", "Output", "Save the aggregated and normed emission values of each vehicle in CSV");
130 
131  oc.addOptionSubTopic("Emissions");
132  oc.doRegister("phemlight-path", new Option_FileName("./PHEMlight/"));
133  oc.addDescription("phemlight-path", "Emissions", "Determines where to load PHEMlight definitions from.");
134 
136  oc.doRegister("quiet", 'q', new Option_Bool(false));
137  oc.addDescription("quiet", "Report", "Not writing anything.");
138 
139  // run
140  int ret = 0;
141  bool quiet = false;
142  try {
143  // initialise the application system (messaging, xml, options)
144  XMLSubSys::init();
145  OptionsIO::setArgs(argc, argv);
148  if (oc.processMetaOptions(argc < 2)) {
150  return 0;
151  }
152 
153  quiet = oc.getBool("quiet");
154  if (!oc.isSet("timeline-file") && !oc.isSet("netstate-file")) {
155  throw ProcessError("Either a timeline or a netstate / amitran file must be given.");
156  }
157  if (!oc.isSet("output-file") && (oc.isSet("timeline-file") || !oc.isSet("emission-output"))) {
158  throw ProcessError("The output file must be given.");
159  }
160  std::ostream* out = 0;
161  if (oc.isSet("output-file")) {
162  out = new std::ofstream(oc.getString("output-file").c_str());
163  }
164  OutputDevice::createDeviceByOption("emission-output", "emission-export", "emission_file.xsd");
165  OutputDevice* xmlOut = 0;
166  if (oc.isSet("emission-output")) {
167  xmlOut = &OutputDevice::getDeviceByOption("emission-output");
168  } else if (out == 0) {
169  out = &std::cout;
170  }
171  std::ostream* sumOut = 0;
172  if (oc.isSet("sum-output")) {
173  sumOut = new std::ofstream(oc.getString("sum-output").c_str());
174  (*sumOut) << "Vehicle,Cycle,Time,Speed,Gradient,Acceleration,FC,FCel,CO2,NOx,CO,HC,PM" << std::endl;
175  }
176 
177  const SUMOEmissionClass defaultClass = PollutantsInterface::getClassByName(oc.getString("emission-class"));
178  const bool computeA = oc.getBool("compute-a") || oc.getBool("compute-a.forward");
179  TrajectoriesHandler handler(computeA, oc.getBool("compute-a.forward"), oc.getBool("compute-a.zero-correction"), defaultClass, oc.getFloat("slope"), out, xmlOut);
180 
181  if (oc.isSet("timeline-file")) {
182  int skip = oc.getBool("skip-first") ? 1 : oc.getInt("timeline-file.skip");
183  const bool inKMH = oc.getBool("kmh");
184  const bool haveSlope = oc.getBool("have-slope");
185  double l = 0;
186  double totalA = 0;
187  double totalS = 0;
188  int time = 0;
189 
190  LineReader lr(oc.getString("timeline-file"));
191  while (lr.hasMore()) {
192  std::string line = lr.readLine();
193  if (skip > 0) {
194  skip--;
195  continue;
196  }
197  StringTokenizer st(StringUtils::prune(line), oc.getString("timeline-file.separator"));
198  if (st.hasNext()) {
199  try {
200  double t = TplConvert::_2double<char>(st.next().c_str());
201  double v = 0;
202  if (st.hasNext()) {
203  v = TplConvert::_2double<char>(st.next().c_str());
204  } else {
205  v = t;
206  t = time;
207  }
208  if (inKMH) {
209  v /= 3.6;
210  }
211  double a = !computeA && st.hasNext() ? TplConvert::_2double<char>(st.next().c_str()) : TrajectoriesHandler::INVALID_VALUE;
212  double s = haveSlope && st.hasNext() ? TplConvert::_2double<char>(st.next().c_str()) : TrajectoriesHandler::INVALID_VALUE;
213  if (handler.writeEmissions(*out, "", defaultClass, t, v, a, s)) {
214  l += v;
215  totalA += a;
216  totalS += s;
217  time++;
218  }
219  } catch (EmptyData&) {
220  throw ProcessError("Missing an entry in line '" + line + "'.");
221  } catch (NumberFormatException&) {
222  throw ProcessError("Not numeric entry in line '" + line + "'.");
223  }
224  }
225  }
226  if (!quiet) {
227  std::cout << "sums" << std::endl
228  << "length:" << l << std::endl;
229  }
230  if (sumOut != 0) {
231  (*sumOut) << oc.getString("emission-class") << "," << lr.getFileName() << "," << time << ","
232  << (l / time * 3.6) << "," << (totalS / time) << "," << (totalA / time) << ",";
233  handler.writeNormedSums(*sumOut, "", l);
234  }
235  }
236  if (oc.isSet("netstate-file")) {
237  XMLSubSys::runParser(handler, oc.getString("netstate-file"));
238  }
239  if (!quiet) {
240  handler.writeSums(std::cout, "");
241  }
242  } catch (InvalidArgument& e) {
244  MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
245  ret = 1;
246  } catch (ProcessError& e) {
247  if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
249  }
250  MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
251  ret = 1;
252 #ifndef _DEBUG
253  } catch (...) {
254  MsgHandler::getErrorInstance()->inform("Quitting (on unknown error).", false);
255  ret = 1;
256 #endif
257  }
259  if (ret == 0 && !quiet) {
260  std::cout << "Success." << std::endl;
261  }
262  return ret;
263 }
264 
265 
266 
267 /****************************************************************************/
268 
void doRegister(const std::string &name, Option *v)
Adds an option under the given name.
Definition: OptionsCont.cpp:81
static void init()
Initialises the xml-subsystem.
Definition: XMLSubSys.cpp:53
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:75
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
static void getOptions(const bool commandLineOnly=false)
Parses the command line arguments and loads the configuration.
Definition: OptionsIO.cpp:82
static void addReportOptions(OptionsCont &oc)
Adds reporting options to the given container.
Definition: SystemFrame.cpp:71
bool readLine(LineHandler &lh)
Reads a single (the next) line from the file and reports it to the given LineHandler.
Definition: LineReader.cpp:75
Retrieves a file linewise and reports the lines to a handler.
Definition: LineReader.h:57
void setApplicationDescription(const std::string &appDesc)
Sets the application description.
int main(int argc, char **argv)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false)
Runs the given handler on the given file; returns if everything&#39;s ok.
Definition: XMLSubSys.cpp:109
static void close()
Closes all of an applications subsystems.
static void addConfigurationOptions(OptionsCont &oc)
Adds configuration options to the given container.
Definition: SystemFrame.cpp:46
static void setArgs(int argc, char **argv)
Stores the command line arguments for later parsing.
Definition: OptionsIO.cpp:61
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:64
void addSynonyme(const std::string &name1, const std::string &name2, bool isDeprecated=false)
Adds a synonyme for an options name (any order)
static const int INVALID_VALUE
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
int SUMOEmissionClass
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool processMetaOptions(bool missingOptions)
Checks for help and configuration output, returns whether we should exit.
void addOptionSubTopic(const std::string &topic)
Adds an option subtopic.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
#define VERSION_STRING
Definition: config.h:210
static std::string prune(const std::string &str)
Removes trailing and leading whitechars.
Definition: StringUtils.cpp:51
An integer-option.
Definition: Option.h:312
static SUMOEmissionClass getClassByName(const std::string &eClass, const SUMOVehicleClass vc=SVC_IGNORING)
Checks whether the string describes a known vehicle class.
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
An XML-Handler for amitran and netstate trajectories.
void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:84
A storage for options typed value containers)
Definition: OptionsCont.h:98
static bool createDeviceByOption(const std::string &optionName, const std::string &rootElement="", const std::string &schemaFile="")
Creates the device using the output definition stored in the named option.
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:70
void addDescription(const std::string &name, const std::string &subtopic, const std::string &description)
Adds a description for an option.
void setApplicationName(const std::string &appName, const std::string &fullName)
Sets the application name.