1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-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 /****************************************************************************/
10 /// @file    NIImporter_OpenDrive.h
11 /// @author  Daniel Krajzewicz
12 /// @author  Jakob Erdmann
13 /// @author  Michael Behrisch
14 /// @date    Mon, 14.04.2008
15 /// @version $Id$
16 ///
17 // Importer for networks stored in openDrive format
18 /****************************************************************************/
19 #ifndef NIImporter_OpenDrive_h
20 #define NIImporter_OpenDrive_h
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #include <config.h>
27 
28 #include <string>
29 #include <map>
30 #include <utils/xml/GenericSAXHandler.h>
31 #include <utils/geom/PositionVector.h>
32 
33 
34 // ===========================================================================
35 // class declarations
36 // ===========================================================================
37 class NBNetBuilder;
38 class NBEdge;
39 class OptionsCont;
40 class NBNode;
41 class NBNodeCont;
42 
43 
44 #define UNSET_CONNECTION 100000
45 
46 // ===========================================================================
47 // class definitions
48 // ===========================================================================
49 /**
50  * @class NIImporter_OpenDrive
51  * @brief Importer for networks stored in openDrive format
52  *
53  */
54 class NIImporter_OpenDrive : public GenericSAXHandler {
55 public:
56     /** @brief Loads content of the optionally given SUMO file
57      *
58      * If the option "opendrive-files" is set, the file stored therein is read and
59      *  the network definition stored therein is stored within the given network
60      *  builder.
61      *
62      * If the option "opendrive-files" is not set, this method simply returns.
63      *
64      * The loading is done by parsing the network definition as an XML file
65      *  using the SAXinterface and handling the incoming data via this class'
66      *  methods.
67      *
68      * @param[in] oc The options to use
69      * @param[in] nb The network builder to fill
70      */
71     static void loadNetwork(const OptionsCont& oc, NBNetBuilder& nb);
72 
73 
74 protected:
75 
76     /**
77      * @enum OpenDriveXMLTag
78      * @brief Numbers representing openDrive-XML - element names
79      * @see GenericSAXHandler
80      */
81     enum OpenDriveXMLTag {
82         OPENDRIVE_TAG_NOTHING,
83         OPENDRIVE_TAG_HEADER,
84         OPENDRIVE_TAG_ROAD,
85         OPENDRIVE_TAG_PREDECESSOR,
86         OPENDRIVE_TAG_SUCCESSOR,
87         /// @todo OPENDRIVE_TAG_NEIGHBOR,
88         /// @todo OPENDRIVE_TAG_TYPE,
89         OPENDRIVE_TAG_GEOMETRY,
90         OPENDRIVE_TAG_LINE,
91         OPENDRIVE_TAG_SPIRAL,
92         OPENDRIVE_TAG_ARC,
93         OPENDRIVE_TAG_POLY3,
94         OPENDRIVE_TAG_PARAMPOLY3,
95         OPENDRIVE_TAG_LANESECTION,
96         OPENDRIVE_TAG_LANEOFFSET,
97         OPENDRIVE_TAG_LEFT,
98         OPENDRIVE_TAG_CENTER,
99         OPENDRIVE_TAG_RIGHT,
100         OPENDRIVE_TAG_LANE,
101         OPENDRIVE_TAG_SIGNAL,
102         OPENDRIVE_TAG_JUNCTION,
103         OPENDRIVE_TAG_CONNECTION,
104         OPENDRIVE_TAG_LANELINK,
105         OPENDRIVE_TAG_WIDTH,
106         OPENDRIVE_TAG_SPEED,
107         OPENDRIVE_TAG_ELEVATION,
108         OPENDRIVE_TAG_GEOREFERENCE,
109         OPENDRIVE_TAG_OBJECT,
110         OPENDRIVE_TAG_REPEAT
111     };
112 
113 
114     /**
115      * @enum OpenDriveXMLAttr
116      * @brief Numbers representing openDrive-XML - attributes
117      * @see GenericSAXHandler
118      */
119     enum OpenDriveXMLAttr {
120         OPENDRIVE_ATTR_NOTHING,
121         OPENDRIVE_ATTR_REVMAJOR,
122         OPENDRIVE_ATTR_REVMINOR,
123         OPENDRIVE_ATTR_ID,
124         OPENDRIVE_ATTR_LENGTH,
125         OPENDRIVE_ATTR_WIDTH,
126         OPENDRIVE_ATTR_RADIUS,
127         OPENDRIVE_ATTR_DISTANCE,
128         OPENDRIVE_ATTR_TSTART,
129         OPENDRIVE_ATTR_TEND,
130         OPENDRIVE_ATTR_WIDTHSTART,
131         OPENDRIVE_ATTR_WIDTHEND,
132         OPENDRIVE_ATTR_JUNCTION,
133         OPENDRIVE_ATTR_ELEMENTTYPE,
134         OPENDRIVE_ATTR_ELEMENTID,
135         OPENDRIVE_ATTR_CONTACTPOINT,
136         OPENDRIVE_ATTR_S,
137         OPENDRIVE_ATTR_T,
138         OPENDRIVE_ATTR_X,
139         OPENDRIVE_ATTR_Y,
140         OPENDRIVE_ATTR_HDG,
141         OPENDRIVE_ATTR_CURVSTART,
142         OPENDRIVE_ATTR_CURVEND,
143         OPENDRIVE_ATTR_CURVATURE,
144         OPENDRIVE_ATTR_A,
145         OPENDRIVE_ATTR_B,
146         OPENDRIVE_ATTR_C,
147         OPENDRIVE_ATTR_D,
148         OPENDRIVE_ATTR_AU,
149         OPENDRIVE_ATTR_BU,
150         OPENDRIVE_ATTR_CU,
151         OPENDRIVE_ATTR_DU,
152         OPENDRIVE_ATTR_AV,
153         OPENDRIVE_ATTR_BV,
154         OPENDRIVE_ATTR_CV,
155         OPENDRIVE_ATTR_DV,
156         OPENDRIVE_ATTR_PRANGE,
157         OPENDRIVE_ATTR_TYPE,
158         OPENDRIVE_ATTR_LEVEL,
159         OPENDRIVE_ATTR_ORIENTATION,
160         OPENDRIVE_ATTR_DYNAMIC,
161         OPENDRIVE_ATTR_INCOMINGROAD,
162         OPENDRIVE_ATTR_CONNECTINGROAD,
163         OPENDRIVE_ATTR_FROM,
164         OPENDRIVE_ATTR_TO,
165         OPENDRIVE_ATTR_MAX,
166         OPENDRIVE_ATTR_SOFFSET,
167         OPENDRIVE_ATTR_NAME,
168         OPENDRIVE_ATTR_UNIT    // xodr v1.4
169     };
170 
171 
172     /** @brief OpenDrive link type enumeration
173      */
174     enum LinkType {
175         OPENDRIVE_LT_SUCCESSOR,
176         OPENDRIVE_LT_PREDECESSOR
177     };
178 
179 
180     /** @brief OpenDrive element type enumeration
181      */
182     enum ElementType {
183         OPENDRIVE_ET_UNKNOWN,
184         OPENDRIVE_ET_ROAD,
185         OPENDRIVE_ET_JUNCTION
186     };
187 
188 
189     /** @brief OpenDrive contact type enumeration
190      */
191     enum ContactPoint {
192         OPENDRIVE_CP_UNKNOWN,
193         OPENDRIVE_CP_START,
194         OPENDRIVE_CP_END
195     };
196 
197     /** @brief OpenDrive geometry type enumeration
198      */
199     enum GeometryType {
200         OPENDRIVE_GT_UNKNOWN,
201         OPENDRIVE_GT_LINE,
202         OPENDRIVE_GT_SPIRAL,
203         OPENDRIVE_GT_ARC,
204         OPENDRIVE_GT_POLY3,
205         OPENDRIVE_GT_PARAMPOLY3 // rev 1.4
206     };
207 
208 
209 
210     /**
211      * @struct OpenDriveLink
212      * @brief Representation of an OpenDrive link
213      */
214     struct OpenDriveLink {
215         /** @brief Constructor
216          * @param[in] linkTypeArg The link type
217          * @param[in] elementIDArg The element id
218          */
OpenDriveLinkOpenDriveLink219         OpenDriveLink(LinkType linkTypeArg, const std::string& elementIDArg)
220             : linkType(linkTypeArg), elementID(elementIDArg),
221               elementType(OPENDRIVE_ET_UNKNOWN), contactPoint(OPENDRIVE_CP_UNKNOWN) { }
222 
223         LinkType linkType;
224         std::string elementID;
225         ElementType elementType;
226         ContactPoint contactPoint;
227     };
228 
229 
230     /**
231      * @struct OpenDriveGeometry
232      * @brief Representation of an OpenDrive geometry part
233      */
234     struct OpenDriveGeometry {
235         /** @brief Constructor
236          * @param[in] lengthArg The length of this geometry part
237          * @param[in] sArg The offset from the start, counted from the begin
238          * @param[in] xArg x-position at this part's begin
239          * @param[in] yArg y-position at this part's begin
240          * @param[in] hdgArg heading at this part's begin
241          */
OpenDriveGeometryOpenDriveGeometry242         OpenDriveGeometry(double lengthArg, double sArg, double xArg, double yArg, double hdgArg)
243             : length(lengthArg), s(sArg), x(xArg), y(yArg), hdg(hdgArg),
244               type(OPENDRIVE_GT_UNKNOWN) { }
245 
246         double length;
247         double s;
248         double x;
249         double y;
250         double hdg;
251         GeometryType type;
252         std::vector<double> params;
253     };
254 
255     /**
256      * @struct OpenDriveElevation
257      * @brief Coefficients of an elevation profile (3rd degree polynomial)
258      */
259     struct Poly3 {
260         /** @brief Constructor
261          * @param[in] s The start offset
262          * @param[in] a constant
263          * @param[in] b first order
264          * @param[in] c second order
265          * @param[in] d third order
266          */
Poly3Poly3267         Poly3(double _s, double _a, double _b, double _c, double _d) :
268             s(_s), a(_a), b(_b), c(_c), d(_d) {}
269 
computeAtPoly3270         double computeAt(double pos) const {
271             const double ds = pos - s;
272             return a + b * ds + c * ds * ds + d * ds * ds * ds;
273         }
274 
275         double s;
276         double a;
277         double b;
278         double c;
279         double d;
280     };
281 
282     /// LaneOffset has the same fields as Elevation
283     typedef Poly3 OpenDriveElevation;
284     typedef Poly3 OpenDriveLaneOffset;
285     typedef Poly3 OpenDriveWidth;
286 
287 
288     /**
289      * @struct OpenDriveLane
290      * @brief Representation of a lane
291      */
292     struct OpenDriveLane {
293         /** @brief Constructor
294          * @param[in] idArg The OpenDrive id of the lane
295          * @param[in] levelArg The level
296          * @param[in] typeArg type of the lane
297          */
OpenDriveLaneOpenDriveLane298         OpenDriveLane(int idArg, const std::string& levelArg, const std::string& typeArg) :
299             id(idArg), level(levelArg), type(typeArg), successor(UNSET_CONNECTION), predecessor(UNSET_CONNECTION),
300             speed(0), width(NBEdge::UNSPECIFIED_WIDTH) { }
301 
302         int id; //!< The lane's id
303         std::string level; //!< The lane's level (not used)
304         std::string type; //!< The lane's type
305         int successor; //!< The lane's successor lane
306         int predecessor; //!< The lane's predecessor lane
307         std::vector<std::pair<double, double> > speeds; //!< List of positions/speeds of speed changes
308         double speed; //!< The lane's speed (set in post-processing)
309         double width; //The lane's maximum width
310         std::vector<OpenDriveWidth> widthData;
311     };
312 
313 
314     /**
315      * @struct OpenDriveLaneSection
316      * @brief Representation of a lane section
317      */
318     struct OpenDriveLaneSection {
319         /** @brief Constructor
320          * @param[in] sArg The offset from the start, counted from the begin
321          */
322         OpenDriveLaneSection(double sArg);
323 
324 
325         /** @brief Build the mapping from OpenDrive to SUMO lanes
326          *
327          * Not all lanes are converted to SUMO-lanes; the mapping includes only those
328          * which are included in the SUMO network.
329          * @param[in] tc The type container needed to determine whether a lane shall be imported by using the lane's type
330          */
331         void buildLaneMapping(const NBTypeCont& tc);
332 
333 
334         /** @brief Returns the links from the previous to this lane section
335          * @param[in] dir The OpenDrive-direction of drive
336          * @param[in] pre The previous lane section
337          * @return which lane is approached from which lane of the given previous lane section
338          */
339         std::map<int, int> getInnerConnections(OpenDriveXMLTag dir, const OpenDriveLaneSection& prev);
340 
341 
342         bool buildSpeedChanges(const NBTypeCont& tc, std::vector<OpenDriveLaneSection>& newSections);
343         OpenDriveLaneSection buildLaneSection(double startPos);
344 
345         /// @brief The starting offset of this lane section
346         double s;
347         /// @brief The original starting offset of this lane section (differs from s if the section had to be split)
348         double sOrig;
349         /// @brief A mapping from OpenDrive to SUMO-index (the first is signed, the second unsigned)
350         std::map<int, int> laneMap;
351         /// @brief The lanes, sorted by their direction
352         std::map<OpenDriveXMLTag, std::vector<OpenDriveLane> > lanesByDir;
353         /// @brief The id (generic, without the optionally leading '-') of the edge generated for this section
354         std::string sumoID;
355         /// @brief The number of lanes on the right and on the left side, respectively
356         int rightLaneNumber, leftLaneNumber;
357         /// @brief the composite type built from all used lane types
358         std::string rightType;
359         std::string leftType;
360     };
361 
362 
363 
364     /**
365      * @struct OpenDriveSignal
366      * @brief Representation of a signal
367      */
368     struct OpenDriveSignal {
369         /** @brief Constructor
370          * @param[in] idArg The OpenDrive id of the signal
371          * @param[in] typeArg The type of the signal
372          * @param[in] nameArg The type of the signal
373          * @param[in] orientationArg The direction the signal belongs to
374          * @param[in] dynamicArg Whether the signal is dynamic
375          * @param[in] sArg The offset from the start, counted from the begin
376          */
OpenDriveSignalOpenDriveSignal377         OpenDriveSignal(const std::string& idArg, const std::string typeArg, const std::string nameArg, int orientationArg, bool dynamicArg, double sArg)
378             : id(idArg), type(typeArg), name(nameArg), orientation(orientationArg), dynamic(dynamicArg), s(sArg) { }
379 
380         std::string id;
381         std::string type;
382         std::string name;
383         int orientation;
384         bool dynamic;
385         double s;
386     };
387 
388 
389     /**
390      * @struct Connection
391      * @brief A connection between two roads
392      */
393     struct Connection {
394         std::string fromEdge;
395         std::string toEdge;
396         int fromLane;
397         int toLane;
398         ContactPoint fromCP;
399         ContactPoint toCP;
400         bool all;
401         std::string origID;
402         int origLane;
403         PositionVector shape;
404 
getDescriptionConnection405         std::string getDescription() const {
406             return "Connection from=" + fromEdge + "_" + toString(fromLane)
407                    + " to=" + toEdge + "_" + toString(toLane)
408                    + " fromCP=" + (fromCP == OPENDRIVE_CP_START ? "start" : fromCP == OPENDRIVE_CP_END ? "end" : "unknown")
409                    + " toCP=" + (toCP == OPENDRIVE_CP_START ? "start" : toCP == OPENDRIVE_CP_END ? "end" : "unknown")
410                    + " all=" + toString(all);
411             //+ " origID=" + origID + " origLane=" + toString(origLane);
412         }
413     };
414 
415     /**
416      * @struct Object
417      * @brief A road object (e.g. parkingSpace)
418      */
419     struct OpenDriveObject {
420         std::string type;
421         std::string name;
422         std::string id;
423         double s;
424         double t;
425         double zOffset;
426         double length;
427         double width;
428         double height;
429         double radius;
430         double hdg;
431         double pitch;
432         double roll;
433     };
434 
435     /**
436      * @struct OpenDriveEdge
437      * @brief Representation of an openDrive "link"
438      */
439     struct OpenDriveEdge {
OpenDriveEdgeOpenDriveEdge440         OpenDriveEdge(const std::string& idArg, const std::string& streetNameArg, const std::string& junctionArg, double lengthArg) :
441             id(idArg),
442             streetName(streetNameArg),
443             junction(junctionArg),
444             length(lengthArg),
445             from(0),
446             to(0) {
447             isInner = junction != "" && junction != "-1";
448         }
449 
450 
451         /** @brief Returns the edge's priority, regarding the direction
452          *
453          * The priority is determined by evaluating the signs located at the road
454          * @param[in] dir The direction which priority shall be returned
455          * @return The priority of the given direction
456          */
457         int getPriority(OpenDriveXMLTag dir) const;
458 
459 
460         /// @brief The id of the edge
461         std::string id;
462         /// @brief The road name of the edge
463         std::string streetName;
464         /// @brief The id of the junction the edge belongs to
465         std::string junction;
466         /// @brief The length of the edge
467         double length;
468         std::vector<OpenDriveLink> links;
469         std::vector<OpenDriveGeometry> geometries;
470         std::vector<OpenDriveElevation> elevations;
471         std::vector<OpenDriveLaneOffset> offsets;
472         NBNode* from;
473         NBNode* to;
474         PositionVector geom;
475         std::vector<OpenDriveLaneSection> laneSections;
476         std::vector<OpenDriveSignal> signals;
477         std::set<Connection> connections;
478         std::vector<OpenDriveObject> objects;
479         bool isInner;
480     };
481 
482 
483     /** @brief A class for sorting lane sections by their s-value */
484     class sections_by_s_sorter {
485     public:
486         /// @brief Constructor
sections_by_s_sorter()487         explicit sections_by_s_sorter() { }
488 
489         /// @brief Sorting function; compares OpenDriveLaneSection::s
operator()490         int operator()(const OpenDriveLaneSection& ls1, const OpenDriveLaneSection& ls2) {
491             return ls1.s < ls2.s;
492         }
493     };
494 
495     /* @brief A class for search in position/speed tuple vectors for the given position */
496     class same_position_finder {
497     public:
498         /** @brief constructor */
same_position_finder(double pos)499         explicit same_position_finder(double pos) : myPosition(pos) { }
500 
501         /** @brief the comparing function */
operator()502         bool operator()(const std::pair<double, double>& ps) {
503             return ps.first == myPosition;
504         }
505 
506     private:
507         same_position_finder& operator=(const same_position_finder&); // just to avoid a compiler warning
508     private:
509         /// @brief The position to search for
510         double myPosition;
511 
512     };
513 
514 protected:
515     /** @brief Constructor
516      * @param[in] tc The type container used to determine whether a lane shall kept
517      * @param[in] nc The edge map to fill
518      */
519     NIImporter_OpenDrive(const NBTypeCont& tc, std::map<std::string, OpenDriveEdge*>& edges);
520 
521 
522     /// @brief Destructor
523     ~NIImporter_OpenDrive();
524 
525 
526 
527     /// @name inherited from GenericSAXHandler
528     //@{
529 
530     /** @brief Called on the opening of a tag;
531      *
532      * In dependence to the obtained type, an appropriate parsing
533      *  method is called ("addEdge" if an edge encounters, f.e.).
534      *
535      * @param[in] element ID of the currently opened element
536      * @param[in] attrs Attributes within the currently opened element
537      * @exception ProcessError If something fails
538      * @see GenericSAXHandler::myStartElement
539      */
540     void myStartElement(int element, const SUMOSAXAttributes& attrs);
541 
542     /**
543      * @brief Callback method for characters to implement by derived classes
544      *
545      * Called by "endElement" (see there).
546      * @param[in] element The opened element, given as a int
547      * @param[in] chars The complete embedded character string
548      * @exceptions ProcessError These method may throw a ProcessError if something fails
549      */
550     void myCharacters(int element, const std::string& chars);
551 
552 
553     /** @brief Called when a closing tag occurs
554      *
555      * @param[in] element ID of the currently opened element
556      * @exception ProcessError If something fails
557      * @see GenericSAXHandler::myEndElement
558      */
559     void myEndElement(int element);
560     //@}
561 
562 
563 
564 private:
565     void addLink(LinkType lt, const std::string& elementType, const std::string& elementID,
566                  const std::string& contactPoint);
567     void addGeometryShape(GeometryType type, const std::vector<double>& vals);
568     static void setEdgeLinks2(OpenDriveEdge& e, const std::map<std::string, OpenDriveEdge*>& edges);
569     static void buildConnectionsToOuter(const Connection& c, const std::map<std::string, OpenDriveEdge*>& innerEdges, std::vector<Connection>& into, std::set<Connection>& seen);
570     static bool laneSectionsConnected(OpenDriveEdge* edge, int in, int out);
571     friend bool operator<(const Connection& c1, const Connection& c2);
572     static std::string revertID(const std::string& id);
573     const NBTypeCont& myTypeContainer;
574     OpenDriveEdge myCurrentEdge;
575 
576     std::map<std::string, OpenDriveEdge*>& myEdges;
577     std::vector<int> myElementStack;
578     OpenDriveXMLTag myCurrentLaneDirection;
579     std::string myCurrentJunctionID;
580     std::string myCurrentIncomingRoad;
581     std::string myCurrentConnectingRoad;
582     ContactPoint myCurrentContactPoint;
583     bool myConnectionWasEmpty;
584 
585     static bool myImportAllTypes;
586     static bool myImportWidths;
587     static double myMinWidth;
588     static bool myImportInternalShapes;
589 
590 
591 protected:
592     /** @brief Builds a node or returns the already built
593      *
594      * If the node is already known, it is returned. Otherwise, the
595      *  node is built. If the newly built node can not be added to
596      *  the container, a ProcessError is thrown.
597      *  Otherwise this node is returned.
598      *
599      * @param[in] id The id of the node to build/get
600      * @param[in, changed] pos The position of the node to build/get
601      * @param[filled] nc The node container to retrieve/add the node to
602      * @return The retrieved/built node
603      * @exception ProcessError If the node could not be built/retrieved
604      */
605     static NBNode* getOrBuildNode(const std::string& id, const Position& pos, NBNodeCont& nc);
606 
607 
608     static PositionVector geomFromLine(const OpenDriveEdge& e, const OpenDriveGeometry& g, double resolution);
609     static PositionVector geomFromSpiral(const OpenDriveEdge& e, const OpenDriveGeometry& g, double resolution);
610     static PositionVector geomFromArc(const OpenDriveEdge& e, const OpenDriveGeometry& g, double resolution);
611     static PositionVector geomFromPoly(const OpenDriveEdge& e, const OpenDriveGeometry& g, double resolution);
612     static PositionVector geomFromParamPoly(const OpenDriveEdge& e, const OpenDriveGeometry& g, double resolution);
613     static Position calculateStraightEndPoint(double hdg, double length, const Position& start);
614     static void calculateCurveCenter(double* ad_x, double* ad_y, double ad_radius, double ad_hdg);
615     static void calcPointOnCurve(double* ad_x, double* ad_y, double ad_centerX, double ad_centerY,
616                                  double ad_r, double ad_length);
617 
618 
619     /** @brief Computes a polygon representation of each edge's geometry
620      * @param[in] edges The edges which geometries shall be converted
621      */
622     static void computeShapes(std::map<std::string, OpenDriveEdge*>& edges);
623 
624     static bool hasNonLinearElevation(OpenDriveEdge& e);
625 
626     /** @brief Rechecks lane sections of the given edges
627      *
628      *
629      * @param[in] edges The edges which lane sections shall be reviewed
630      */
631     static void revisitLaneSections(const NBTypeCont& tc, std::map<std::string, OpenDriveEdge*>& edges);
632 
633     static void setNodeSecure(NBNodeCont& nc, OpenDriveEdge& e,
634                               const std::string& nodeID, NIImporter_OpenDrive::LinkType lt);
635 
636 
637     static void splitMinWidths(OpenDriveEdge* e, const NBTypeCont& tc, double minDist);
638 
639     static void findWidthSplit(const NBTypeCont& tc, std::vector<OpenDriveLane>& lanes,
640                                int section, double sectionStart, double sectionEnd,
641                                std::vector<double>& splitPositions);
642 
643     static void setStraightConnections(std::vector<OpenDriveLane>& lanes);
644     static void recomputeWidths(OpenDriveLaneSection& sec, double start, double end, double sectionStart, double sectionEnd);
645     static void recomputeWidths(std::vector<OpenDriveLane>& lanes, double start, double end, double sectionStart, double sectionEnd);
646 
647     /// The names of openDrive-XML elements (for passing to GenericSAXHandler)
648     static StringBijection<int>::Entry openDriveTags[];
649 
650     /// The names of openDrive-XML attributes (for passing to GenericSAXHandler)
651     static StringBijection<int>::Entry openDriveAttrs[];
652 
653 
654 
655 };
656 
657 
658 #endif
659 
660 /****************************************************************************/
661 
662