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