From f9baef5050cee4978078ca41f86fb1953f81ba6e Mon Sep 17 00:00:00 2001 From: Axel1092 Date: Wed, 15 Jul 2020 12:12:58 +0200 Subject: [PATCH] Added OSM to XODR to PythonAPI. --- PythonAPI/carla/source/libcarla/Converter.cpp | 2 +- Util/Converter/src/Converter.cpp | 67 +++++++++++++--- Util/Converter/src/Converter.h | 2 +- .../netimport/NIImporter_OpenStreetMap.cpp | 80 ++++++++++++------- .../src/netwrite/NWWriter_OpenDrive.cpp | 7 +- .../Converter/src/utils/options/OptionsCont.h | 3 + .../src/utils/options/OptionsParser.cpp | 21 +++++ .../src/utils/options/OptionsParser.h | 4 + Util/Converter/src/utils/xml/XMLSubSys.cpp | 37 +++++++++ Util/Converter/src/utils/xml/XMLSubSys.h | 2 + 10 files changed, 183 insertions(+), 42 deletions(-) diff --git a/PythonAPI/carla/source/libcarla/Converter.cpp b/PythonAPI/carla/source/libcarla/Converter.cpp index 973c2e098..e267a34e2 100644 --- a/PythonAPI/carla/source/libcarla/Converter.cpp +++ b/PythonAPI/carla/source/libcarla/Converter.cpp @@ -17,7 +17,7 @@ void export_converter() { using namespace converter; using namespace boost::python; - def("convert_to_odr", &ConvertOSMToOpenDRIVE, (arg("osm_file"))); + def("convert_to_odr", &ConvertOSMToOpenDRIVE, (arg("osm_file"), arg("offsetX") = 0, arg("offsetY") = 0)); // class_("Converter", init<>()) // .def("convert_to_odr", &Converter::ConvertOSMToOpenDRIVE, (arg("osm_file"))) diff --git a/Util/Converter/src/Converter.cpp b/Util/Converter/src/Converter.cpp index cebb51929..f3bbe6c59 100644 --- a/Util/Converter/src/Converter.cpp +++ b/Util/Converter/src/Converter.cpp @@ -66,17 +66,66 @@ namespace converter { return ok; } - std::string ConvertOSMToOpenDRIVE(std::string osm_file) { - OptionsCont::getOptions().clear(); + std::string ConvertOSMToOpenDRIVE(std::string osm_file, double offsetX, double offsetY) { + // std::string OptionsArgs = "--geometry.remove --ramps.guess --edges.join --junctions.join --keep-edges.by-type highway.motorway,highway.motorway_link,highway.trunk,highway.trunk_link,highway.primary,highway.primary_link,highway.secondary,highway.secondary_link,highway.tertiary,highway.tertiary_link,highway.unclassified,highway.residential --tls.discard-loaded --tls.discard-simple --default.lanewidth 4.0 --osm.layer-elevation 4"; + std::vector OptionsArgs = { + "--proj", "+proj=tmerc", + "--geometry.remove", "--ramps.guess", "--edges.join", "--junctions.join", + "--keep-edges.by-type", "highway.motorway,highway.motorway_link,highway.trunk,highway.trunk_link,highway.primary,highway.primary_link,highway.secondary,highway.secondary_link,highway.tertiary,highway.tertiary_link,highway.unclassified,highway.residential", + "--tls.discard-loaded", "--tls.discard-simple", "--default.lanewidth", "4.0", + "--osm.layer-elevation", "4", + "--osm-files", "TRUE", "--opendrive-output", "TRUE", // necessary for now to enable osm input and xodr output + "--offset.x", std::to_string(offsetX), "--offset.y", std::to_string(offsetY) + }; + + // OptionsCont::getOptions().clear(); + OptionsCont& oc = OptionsCont::getOptions(); + oc.input_osm_file = osm_file; + + XMLSubSys::init(); fillOptions(); - - std::string OptionsArgs = "--geometry.remove --ramps.guess --edges.join --junctions.join --keep-edges.by-type highway.motorway,highway.motorway_link,highway.trunk,highway.trunk_link,highway.primary,highway.primary_link,highway.secondary,highway.secondary_link,highway.tertiary,highway.tertiary_link,highway.unclassified,highway.residential --tls.discard-loaded --tls.discard-simple --default.lanewidth 4.0 --osm.layer-elevation 4" - - if(checkOptions()) { - return osm_file + " succesful fail"; - } else { - return osm_file + " sucesful success"; + OptionsIO::setArgs(OptionsArgs); + OptionsIO::getOptions(); + if (oc.processMetaOptions(OptionsArgs.size() < 2)) { + SystemFrame::close(); + return 0; } + XMLSubSys::setValidation(oc.getString("xml-validation"), oc.getString("xml-validation.net")); + if (oc.isDefault("aggregate-warnings")) { + oc.set("aggregate-warnings", "5"); + } + MsgHandler::initOutputOptions(); + if (!checkOptions()) { + throw ProcessError(); + } + RandHelper::initRandGlobal(); + // build the projection + if (!GeoConvHelper::init(oc)) { + throw ProcessError("Could not build projection!"); + } + NBNetBuilder nb; + nb.applyOptions(oc); + // load data + NILoader nl(nb); + nl.load(oc); + // flush aggregated errors and optionally ignore them + MsgHandler::getErrorInstance()->clear(oc.getBool("ignore-errors")); + // check whether any errors occurred + if (MsgHandler::getErrorInstance()->wasInformed()) { + throw ProcessError(); + } + nb.compute(oc); + // check whether any errors occurred + if (MsgHandler::getErrorInstance()->wasInformed()) { + throw ProcessError(); + } + NWFrame::writeNetwork(oc, nb); + + + DistributionCont::clear(); + SystemFrame::close(); + + return oc.output_xodr_file; } diff --git a/Util/Converter/src/Converter.h b/Util/Converter/src/Converter.h index 11cfff930..3f7b4f2ac 100644 --- a/Util/Converter/src/Converter.h +++ b/Util/Converter/src/Converter.h @@ -10,6 +10,6 @@ namespace converter { - std::string ConvertOSMToOpenDRIVE(std::string osm_file); + std::string ConvertOSMToOpenDRIVE(std::string osm_file, double offsetX = 0, double offsetY = 0); } // namespace converter diff --git a/Util/Converter/src/netimport/NIImporter_OpenStreetMap.cpp b/Util/Converter/src/netimport/NIImporter_OpenStreetMap.cpp index f07abaa9a..1c2f07f55 100644 --- a/Util/Converter/src/netimport/NIImporter_OpenStreetMap.cpp +++ b/Util/Converter/src/netimport/NIImporter_OpenStreetMap.cpp @@ -133,31 +133,47 @@ NIImporter_OpenStreetMap::load(const OptionsCont& oc, NBNetBuilder& nb) { std::vector files = oc.getStringVector("osm-files"); // load nodes, first NodesHandler nodesHandler(myOSMNodes, myUniqueNodes, oc); - for (std::vector::const_iterator file = files.begin(); file != files.end(); ++file) { - // nodes - if (!FileHelpers::isReadable(*file)) { - WRITE_ERROR("Could not open osm-file '" + *file + "'."); - return; - } - nodesHandler.setFileName(*file); - PROGRESS_BEGIN_MESSAGE("Parsing nodes from osm-file '" + *file + "'"); - if (!XMLSubSys::runParser(nodesHandler, *file)) { - return; - } - if (nodesHandler.getDuplicateNodes() > 0) { - WRITE_MESSAGE("Found and substituted " + toString(nodesHandler.getDuplicateNodes()) + " osm nodes."); - } - PROGRESS_DONE_MESSAGE(); + // for (std::vector::const_iterator file = files.begin(); file != files.end(); ++file) { + // // nodes + // if (!FileHelpers::isReadable(*file)) { + // WRITE_ERROR("Could not open osm-file '" + *file + "'."); + // return; + // } + // nodesHandler.setFileName(*file); + // PROGRESS_BEGIN_MESSAGE("Parsing nodes from osm-file '" + *file + "'"); + // if (!XMLSubSys::runParser(nodesHandler, *file)) { + // return; + // } + // if (nodesHandler.getDuplicateNodes() > 0) { + // WRITE_MESSAGE("Found and substituted " + toString(nodesHandler.getDuplicateNodes()) + " osm nodes."); + // } + // PROGRESS_DONE_MESSAGE(); + // } + nodesHandler.setFileName("osm_file"); + PROGRESS_BEGIN_MESSAGE("Parsing nodes from osm string"); + if (!XMLSubSys::runParserFromString(nodesHandler, oc.input_osm_file)) { + return; } + if (nodesHandler.getDuplicateNodes() > 0) { + WRITE_MESSAGE("Found and substituted " + toString(nodesHandler.getDuplicateNodes()) + " osm nodes."); + } + PROGRESS_DONE_MESSAGE(); + // load edges, then EdgesHandler edgesHandler(myOSMNodes, myEdges, myPlatformShapes); - for (std::vector::const_iterator file = files.begin(); file != files.end(); ++file) { - // edges - edgesHandler.setFileName(*file); - PROGRESS_BEGIN_MESSAGE("Parsing edges from osm-file '" + *file + "'"); - XMLSubSys::runParser(edgesHandler, *file); - PROGRESS_DONE_MESSAGE(); - } + // for (std::vector::const_iterator file = files.begin(); file != files.end(); ++file) { + // // edges + // edgesHandler.setFileName(*file); + // PROGRESS_BEGIN_MESSAGE("Parsing edges from osm-file '" + *file + "'"); + // XMLSubSys::runParser(edgesHandler, *file); + // PROGRESS_DONE_MESSAGE(); + // } + // edges + edgesHandler.setFileName("osm_file"); + PROGRESS_BEGIN_MESSAGE("Parsing nodes from osm string"); + XMLSubSys::runParserFromString(edgesHandler, oc.input_osm_file); + PROGRESS_DONE_MESSAGE(); + /* Remove duplicate edges with the same shape and attributes */ if (!oc.getBool("osm.skip-duplicates-check")) { @@ -260,13 +276,19 @@ NIImporter_OpenStreetMap::load(const OptionsCont& oc, NBNetBuilder& nb) { // turn-restrictions directly to NBEdges) RelationHandler relationHandler(myOSMNodes, myEdges, &(nb.getPTStopCont()), myPlatformShapes, &nb.getPTLineCont(), oc); - for (std::vector::const_iterator file = files.begin(); file != files.end(); ++file) { - // relations - relationHandler.setFileName(*file); - PROGRESS_BEGIN_MESSAGE("Parsing relations from osm-file '" + *file + "'"); - XMLSubSys::runParser(relationHandler, *file); - PROGRESS_DONE_MESSAGE(); - } + // for (std::vector::const_iterator file = files.begin(); file != files.end(); ++file) { + // // relations + // relationHandler.setFileName(*file); + // PROGRESS_BEGIN_MESSAGE("Parsing relations from osm-file '" + *file + "'"); + // XMLSubSys::runParser(relationHandler, *file); + // PROGRESS_DONE_MESSAGE(); + // } + // relations + relationHandler.setFileName("osm-file"); + PROGRESS_BEGIN_MESSAGE("Parsing nodes from osm string"); + XMLSubSys::runParserFromString(edgesHandler, oc.input_osm_file); + PROGRESS_DONE_MESSAGE(); + } NBNode* diff --git a/Util/Converter/src/netwrite/NWWriter_OpenDrive.cpp b/Util/Converter/src/netwrite/NWWriter_OpenDrive.cpp index c6e664cf1..1acd6a894 100644 --- a/Util/Converter/src/netwrite/NWWriter_OpenDrive.cpp +++ b/Util/Converter/src/netwrite/NWWriter_OpenDrive.cpp @@ -67,7 +67,7 @@ NWWriter_OpenDrive::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { StringBijection edgeMap; StringBijection nodeMap; // - OutputDevice& device = OutputDevice::getDevice(oc.getString("opendrive-output")); + OutputDevice_String device; device << "\n"; device.openTag("OpenDRIVE"); time_t now = time(nullptr); @@ -212,7 +212,10 @@ NWWriter_OpenDrive::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { } device.closeTag(); - device.close(); + + OptionsCont::getOptions().output_xodr_file = device.getString(); + + // device.close(); } diff --git a/Util/Converter/src/utils/options/OptionsCont.h b/Util/Converter/src/utils/options/OptionsCont.h index 084dc8174..34974f292 100644 --- a/Util/Converter/src/utils/options/OptionsCont.h +++ b/Util/Converter/src/utils/options/OptionsCont.h @@ -670,6 +670,9 @@ public: return myFullName; } + std::string input_osm_file; + std::string output_xodr_file; + private: /** @brief Returns the named option * diff --git a/Util/Converter/src/utils/options/OptionsParser.cpp b/Util/Converter/src/utils/options/OptionsParser.cpp index d3718dade..b35b0a07d 100644 --- a/Util/Converter/src/utils/options/OptionsParser.cpp +++ b/Util/Converter/src/utils/options/OptionsParser.cpp @@ -55,6 +55,27 @@ OptionsParser::parse(int argc, char** argv) { return ok; } +bool +OptionsParser::parse(std::vector args) { + bool ok = true; + for (size_t i = 1; i < args.size();) { + try { + int add; + // try to set the current option + if (i < args.size()- 1) { + add = check(args[i].c_str(), args[i + 1].c_str(), ok); + } else { + add = check(args[i].c_str(), nullptr, ok); + } + i += add; + } catch (ProcessError& e) { + WRITE_ERROR("On processing option '" + args[i] + "':\n " + e.what()); + i++; + ok = false; + } + } + return ok; +} int OptionsParser::check(const char* arg1, const char* arg2, bool& ok) { diff --git a/Util/Converter/src/utils/options/OptionsParser.h b/Util/Converter/src/utils/options/OptionsParser.h index 8658e0f08..793444470 100644 --- a/Util/Converter/src/utils/options/OptionsParser.h +++ b/Util/Converter/src/utils/options/OptionsParser.h @@ -22,6 +22,8 @@ #pragma once #include +#include +#include // =========================================================================== // class declarations @@ -55,6 +57,8 @@ public: */ static bool parse(int argc, char** argv); + static bool parse(std::vector args); + private: /** @brief parses the previous arguments * diff --git a/Util/Converter/src/utils/xml/XMLSubSys.cpp b/Util/Converter/src/utils/xml/XMLSubSys.cpp index 202b4d02e..301987241 100644 --- a/Util/Converter/src/utils/xml/XMLSubSys.cpp +++ b/Util/Converter/src/utils/xml/XMLSubSys.cpp @@ -143,5 +143,42 @@ XMLSubSys::runParser(GenericSAXHandler& handler, return !MsgHandler::getErrorInstance()->wasInformed(); } +bool +XMLSubSys::runParserFromString(GenericSAXHandler& handler, + const std::string& xml, const bool isNet) { + std::string file = "String XML"; + MsgHandler::getErrorInstance()->clear(); + try { + XERCES_CPP_NAMESPACE::SAX2XMLReader::ValSchemes validationScheme = isNet ? myNetValidationScheme : myValidationScheme; + if (myNextFreeReader == (int)myReaders.size()) { + myReaders.push_back(new SUMOSAXReader(handler, validationScheme)); + } else { + myReaders[myNextFreeReader]->setValidation(validationScheme); + myReaders[myNextFreeReader]->setHandler(handler); + } + myNextFreeReader++; + std::string prevFile = handler.getFileName(); + handler.setFileName(file); + myReaders[myNextFreeReader - 1]->parseString(xml); + handler.setFileName(prevFile); + myNextFreeReader--; + } catch (AbortParsing&) { + return false; + } catch (ProcessError& e) { + WRITE_ERROR(std::string(e.what()) != std::string("") ? std::string(e.what()) : std::string("Process Error")); + return false; + } catch (const std::runtime_error& re) { + WRITE_ERROR("Runtime error: " + std::string(re.what()) + " while parsing '" + file + "'"); + return false; + } catch (const std::exception& ex) { + WRITE_ERROR("Error occurred: " + std::string(ex.what()) + " while parsing '" + file + "'"); + return false; + } catch (...) { + WRITE_ERROR("Unspecified error occurred wile parsing '" + file + "'"); + return false; + } + return !MsgHandler::getErrorInstance()->wasInformed(); +} + /****************************************************************************/ diff --git a/Util/Converter/src/utils/xml/XMLSubSys.h b/Util/Converter/src/utils/xml/XMLSubSys.h index f465ac378..be77fba99 100644 --- a/Util/Converter/src/utils/xml/XMLSubSys.h +++ b/Util/Converter/src/utils/xml/XMLSubSys.h @@ -146,6 +146,8 @@ public: static bool runParser(GenericSAXHandler& handler, const std::string& file, const bool isNet = false); + static bool runParserFromString(GenericSAXHandler& handler, + const std::string& xml, const bool isNet = false); private: /// @brief The XML Readers used for repeated parsing