├── .gitignore
├── LICENSE
├── README.md
├── __init__.py
├── example.py
├── examples
├── full_junction.py
├── highway_example.py
├── junction_trippel_twoway.py
├── junction_with_signals.py
├── lane_number_change_merge.py
├── multiple_geometries_one_road.py
├── multiple_geometries_one_road_with_objects.py
├── road_merge.py
├── road_merge_w_lane_merge.py
├── road_split.py
├── road_split_w_lane_split.py
└── two_roads.py
├── html
└── pyodrx
│ ├── enumerations.html
│ ├── exceptions.html
│ ├── generators.html
│ ├── geometry.html
│ ├── helpers.html
│ ├── index.html
│ ├── lane.html
│ ├── links.html
│ ├── opendrive.html
│ └── signals.html
├── pyodrx
├── __init__.py
├── enumerations.py
├── exceptions.py
├── generators.py
├── geometry.py
├── helpers.py
├── lane.py
├── links.py
├── opendrive.py
└── signals_objects.py
├── requirements.txt
├── setup.py
├── tests
├── test_geometry.py
├── test_lane.py
├── test_links.py
├── test_opendrive.py
└── test_signals_objects.py
└── xodr_coverage.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.pyo
3 | venv/*
4 | requirements.txt
5 | .idea/*
6 | pyodrx.egg-info/*
7 | *.xodr
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Mozilla Public License Version 2.0
2 | ==================================
3 |
4 | 1. Definitions
5 | --------------
6 |
7 | 1.1. "Contributor"
8 | means each individual or legal entity that creates, contributes to
9 | the creation of, or owns Covered Software.
10 |
11 | 1.2. "Contributor Version"
12 | means the combination of the Contributions of others (if any) used
13 | by a Contributor and that particular Contributor's Contribution.
14 |
15 | 1.3. "Contribution"
16 | means Covered Software of a particular Contributor.
17 |
18 | 1.4. "Covered Software"
19 | means Source Code Form to which the initial Contributor has attached
20 | the notice in Exhibit A, the Executable Form of such Source Code
21 | Form, and Modifications of such Source Code Form, in each case
22 | including portions thereof.
23 |
24 | 1.5. "Incompatible With Secondary Licenses"
25 | means
26 |
27 | (a) that the initial Contributor has attached the notice described
28 | in Exhibit B to the Covered Software; or
29 |
30 | (b) that the Covered Software was made available under the terms of
31 | version 1.1 or earlier of the License, but not also under the
32 | terms of a Secondary License.
33 |
34 | 1.6. "Executable Form"
35 | means any form of the work other than Source Code Form.
36 |
37 | 1.7. "Larger Work"
38 | means a work that combines Covered Software with other material, in
39 | a separate file or files, that is not Covered Software.
40 |
41 | 1.8. "License"
42 | means this document.
43 |
44 | 1.9. "Licensable"
45 | means having the right to grant, to the maximum extent possible,
46 | whether at the time of the initial grant or subsequently, any and
47 | all of the rights conveyed by this License.
48 |
49 | 1.10. "Modifications"
50 | means any of the following:
51 |
52 | (a) any file in Source Code Form that results from an addition to,
53 | deletion from, or modification of the contents of Covered
54 | Software; or
55 |
56 | (b) any new file in Source Code Form that contains any Covered
57 | Software.
58 |
59 | 1.11. "Patent Claims" of a Contributor
60 | means any patent claim(s), including without limitation, method,
61 | process, and apparatus claims, in any patent Licensable by such
62 | Contributor that would be infringed, but for the grant of the
63 | License, by the making, using, selling, offering for sale, having
64 | made, import, or transfer of either its Contributions or its
65 | Contributor Version.
66 |
67 | 1.12. "Secondary License"
68 | means either the GNU General Public License, Version 2.0, the GNU
69 | Lesser General Public License, Version 2.1, the GNU Affero General
70 | Public License, Version 3.0, or any later versions of those
71 | licenses.
72 |
73 | 1.13. "Source Code Form"
74 | means the form of the work preferred for making modifications.
75 |
76 | 1.14. "You" (or "Your")
77 | means an individual or a legal entity exercising rights under this
78 | License. For legal entities, "You" includes any entity that
79 | controls, is controlled by, or is under common control with You. For
80 | purposes of this definition, "control" means (a) the power, direct
81 | or indirect, to cause the direction or management of such entity,
82 | whether by contract or otherwise, or (b) ownership of more than
83 | fifty percent (50%) of the outstanding shares or beneficial
84 | ownership of such entity.
85 |
86 | 2. License Grants and Conditions
87 | --------------------------------
88 |
89 | 2.1. Grants
90 |
91 | Each Contributor hereby grants You a world-wide, royalty-free,
92 | non-exclusive license:
93 |
94 | (a) under intellectual property rights (other than patent or trademark)
95 | Licensable by such Contributor to use, reproduce, make available,
96 | modify, display, perform, distribute, and otherwise exploit its
97 | Contributions, either on an unmodified basis, with Modifications, or
98 | as part of a Larger Work; and
99 |
100 | (b) under Patent Claims of such Contributor to make, use, sell, offer
101 | for sale, have made, import, and otherwise transfer either its
102 | Contributions or its Contributor Version.
103 |
104 | 2.2. Effective Date
105 |
106 | The licenses granted in Section 2.1 with respect to any Contribution
107 | become effective for each Contribution on the date the Contributor first
108 | distributes such Contribution.
109 |
110 | 2.3. Limitations on Grant Scope
111 |
112 | The licenses granted in this Section 2 are the only rights granted under
113 | this License. No additional rights or licenses will be implied from the
114 | distribution or licensing of Covered Software under this License.
115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a
116 | Contributor:
117 |
118 | (a) for any code that a Contributor has removed from Covered Software;
119 | or
120 |
121 | (b) for infringements caused by: (i) Your and any other third party's
122 | modifications of Covered Software, or (ii) the combination of its
123 | Contributions with other software (except as part of its Contributor
124 | Version); or
125 |
126 | (c) under Patent Claims infringed by Covered Software in the absence of
127 | its Contributions.
128 |
129 | This License does not grant any rights in the trademarks, service marks,
130 | or logos of any Contributor (except as may be necessary to comply with
131 | the notice requirements in Section 3.4).
132 |
133 | 2.4. Subsequent Licenses
134 |
135 | No Contributor makes additional grants as a result of Your choice to
136 | distribute the Covered Software under a subsequent version of this
137 | License (see Section 10.2) or under the terms of a Secondary License (if
138 | permitted under the terms of Section 3.3).
139 |
140 | 2.5. Representation
141 |
142 | Each Contributor represents that the Contributor believes its
143 | Contributions are its original creation(s) or it has sufficient rights
144 | to grant the rights to its Contributions conveyed by this License.
145 |
146 | 2.6. Fair Use
147 |
148 | This License is not intended to limit any rights You have under
149 | applicable copyright doctrines of fair use, fair dealing, or other
150 | equivalents.
151 |
152 | 2.7. Conditions
153 |
154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
155 | in Section 2.1.
156 |
157 | 3. Responsibilities
158 | -------------------
159 |
160 | 3.1. Distribution of Source Form
161 |
162 | All distribution of Covered Software in Source Code Form, including any
163 | Modifications that You create or to which You contribute, must be under
164 | the terms of this License. You must inform recipients that the Source
165 | Code Form of the Covered Software is governed by the terms of this
166 | License, and how they can obtain a copy of this License. You may not
167 | attempt to alter or restrict the recipients' rights in the Source Code
168 | Form.
169 |
170 | 3.2. Distribution of Executable Form
171 |
172 | If You distribute Covered Software in Executable Form then:
173 |
174 | (a) such Covered Software must also be made available in Source Code
175 | Form, as described in Section 3.1, and You must inform recipients of
176 | the Executable Form how they can obtain a copy of such Source Code
177 | Form by reasonable means in a timely manner, at a charge no more
178 | than the cost of distribution to the recipient; and
179 |
180 | (b) You may distribute such Executable Form under the terms of this
181 | License, or sublicense it under different terms, provided that the
182 | license for the Executable Form does not attempt to limit or alter
183 | the recipients' rights in the Source Code Form under this License.
184 |
185 | 3.3. Distribution of a Larger Work
186 |
187 | You may create and distribute a Larger Work under terms of Your choice,
188 | provided that You also comply with the requirements of this License for
189 | the Covered Software. If the Larger Work is a combination of Covered
190 | Software with a work governed by one or more Secondary Licenses, and the
191 | Covered Software is not Incompatible With Secondary Licenses, this
192 | License permits You to additionally distribute such Covered Software
193 | under the terms of such Secondary License(s), so that the recipient of
194 | the Larger Work may, at their option, further distribute the Covered
195 | Software under the terms of either this License or such Secondary
196 | License(s).
197 |
198 | 3.4. Notices
199 |
200 | You may not remove or alter the substance of any license notices
201 | (including copyright notices, patent notices, disclaimers of warranty,
202 | or limitations of liability) contained within the Source Code Form of
203 | the Covered Software, except that You may alter any license notices to
204 | the extent required to remedy known factual inaccuracies.
205 |
206 | 3.5. Application of Additional Terms
207 |
208 | You may choose to offer, and to charge a fee for, warranty, support,
209 | indemnity or liability obligations to one or more recipients of Covered
210 | Software. However, You may do so only on Your own behalf, and not on
211 | behalf of any Contributor. You must make it absolutely clear that any
212 | such warranty, support, indemnity, or liability obligation is offered by
213 | You alone, and You hereby agree to indemnify every Contributor for any
214 | liability incurred by such Contributor as a result of warranty, support,
215 | indemnity or liability terms You offer. You may include additional
216 | disclaimers of warranty and limitations of liability specific to any
217 | jurisdiction.
218 |
219 | 4. Inability to Comply Due to Statute or Regulation
220 | ---------------------------------------------------
221 |
222 | If it is impossible for You to comply with any of the terms of this
223 | License with respect to some or all of the Covered Software due to
224 | statute, judicial order, or regulation then You must: (a) comply with
225 | the terms of this License to the maximum extent possible; and (b)
226 | describe the limitations and the code they affect. Such description must
227 | be placed in a text file included with all distributions of the Covered
228 | Software under this License. Except to the extent prohibited by statute
229 | or regulation, such description must be sufficiently detailed for a
230 | recipient of ordinary skill to be able to understand it.
231 |
232 | 5. Termination
233 | --------------
234 |
235 | 5.1. The rights granted under this License will terminate automatically
236 | if You fail to comply with any of its terms. However, if You become
237 | compliant, then the rights granted under this License from a particular
238 | Contributor are reinstated (a) provisionally, unless and until such
239 | Contributor explicitly and finally terminates Your grants, and (b) on an
240 | ongoing basis, if such Contributor fails to notify You of the
241 | non-compliance by some reasonable means prior to 60 days after You have
242 | come back into compliance. Moreover, Your grants from a particular
243 | Contributor are reinstated on an ongoing basis if such Contributor
244 | notifies You of the non-compliance by some reasonable means, this is the
245 | first time You have received notice of non-compliance with this License
246 | from such Contributor, and You become compliant prior to 30 days after
247 | Your receipt of the notice.
248 |
249 | 5.2. If You initiate litigation against any entity by asserting a patent
250 | infringement claim (excluding declaratory judgment actions,
251 | counter-claims, and cross-claims) alleging that a Contributor Version
252 | directly or indirectly infringes any patent, then the rights granted to
253 | You by any and all Contributors for the Covered Software under Section
254 | 2.1 of this License shall terminate.
255 |
256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
257 | end user license agreements (excluding distributors and resellers) which
258 | have been validly granted by You or Your distributors under this License
259 | prior to termination shall survive termination.
260 |
261 | ************************************************************************
262 | * *
263 | * 6. Disclaimer of Warranty *
264 | * ------------------------- *
265 | * *
266 | * Covered Software is provided under this License on an "as is" *
267 | * basis, without warranty of any kind, either expressed, implied, or *
268 | * statutory, including, without limitation, warranties that the *
269 | * Covered Software is free of defects, merchantable, fit for a *
270 | * particular purpose or non-infringing. The entire risk as to the *
271 | * quality and performance of the Covered Software is with You. *
272 | * Should any Covered Software prove defective in any respect, You *
273 | * (not any Contributor) assume the cost of any necessary servicing, *
274 | * repair, or correction. This disclaimer of warranty constitutes an *
275 | * essential part of this License. No use of any Covered Software is *
276 | * authorized under this License except under this disclaimer. *
277 | * *
278 | ************************************************************************
279 |
280 | ************************************************************************
281 | * *
282 | * 7. Limitation of Liability *
283 | * -------------------------- *
284 | * *
285 | * Under no circumstances and under no legal theory, whether tort *
286 | * (including negligence), contract, or otherwise, shall any *
287 | * Contributor, or anyone who distributes Covered Software as *
288 | * permitted above, be liable to You for any direct, indirect, *
289 | * special, incidental, or consequential damages of any character *
290 | * including, without limitation, damages for lost profits, loss of *
291 | * goodwill, work stoppage, computer failure or malfunction, or any *
292 | * and all other commercial damages or losses, even if such party *
293 | * shall have been informed of the possibility of such damages. This *
294 | * limitation of liability shall not apply to liability for death or *
295 | * personal injury resulting from such party's negligence to the *
296 | * extent applicable law prohibits such limitation. Some *
297 | * jurisdictions do not allow the exclusion or limitation of *
298 | * incidental or consequential damages, so this exclusion and *
299 | * limitation may not apply to You. *
300 | * *
301 | ************************************************************************
302 |
303 | 8. Litigation
304 | -------------
305 |
306 | Any litigation relating to this License may be brought only in the
307 | courts of a jurisdiction where the defendant maintains its principal
308 | place of business and such litigation shall be governed by laws of that
309 | jurisdiction, without reference to its conflict-of-law provisions.
310 | Nothing in this Section shall prevent a party's ability to bring
311 | cross-claims or counter-claims.
312 |
313 | 9. Miscellaneous
314 | ----------------
315 |
316 | This License represents the complete agreement concerning the subject
317 | matter hereof. If any provision of this License is held to be
318 | unenforceable, such provision shall be reformed only to the extent
319 | necessary to make it enforceable. Any law or regulation which provides
320 | that the language of a contract shall be construed against the drafter
321 | shall not be used to construe this License against a Contributor.
322 |
323 | 10. Versions of the License
324 | ---------------------------
325 |
326 | 10.1. New Versions
327 |
328 | Mozilla Foundation is the license steward. Except as provided in Section
329 | 10.3, no one other than the license steward has the right to modify or
330 | publish new versions of this License. Each version will be given a
331 | distinguishing version number.
332 |
333 | 10.2. Effect of New Versions
334 |
335 | You may distribute the Covered Software under the terms of the version
336 | of the License under which You originally received the Covered Software,
337 | or under the terms of any subsequent version published by the license
338 | steward.
339 |
340 | 10.3. Modified Versions
341 |
342 | If you create software not governed by this License, and you want to
343 | create a new license for such software, you may create and use a
344 | modified version of this License if you rename the license and remove
345 | any references to the name of the license steward (except to note that
346 | such modified license differs from this License).
347 |
348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary
349 | Licenses
350 |
351 | If You choose to distribute Source Code Form that is Incompatible With
352 | Secondary Licenses under the terms of this version of the License, the
353 | notice described in Exhibit B of this License must be attached.
354 |
355 | Exhibit A - Source Code Form License Notice
356 | -------------------------------------------
357 |
358 | This Source Code Form is subject to the terms of the Mozilla Public
359 | License, v. 2.0. If a copy of the MPL was not distributed with this
360 | file, You can obtain one at http://mozilla.org/MPL/2.0/.
361 |
362 | If it is not possible or desirable to put the notice in a particular
363 | file, then You may include the notice in a location (such as a LICENSE
364 | file in a relevant directory) where a recipient would be likely to look
365 | for such a notice.
366 |
367 | You may add additional accurate notices of copyright ownership.
368 |
369 | Exhibit B - "Incompatible With Secondary Licenses" Notice
370 | ---------------------------------------------------------
371 |
372 | This Source Code Form is "Incompatible With Secondary Licenses", as
373 | defined by the Mozilla Public License, v. 2.0.
374 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # pyodrx
2 |
3 | This project has been absorbed into the [scenariogeneration](https://github.com/pyoscx/scenariogeneration) project.
4 |
5 |
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyoscx/pyodrx/a65407e0fe597131970ec70dfd0fd14c41e70fb7/__init__.py
--------------------------------------------------------------------------------
/example.py:
--------------------------------------------------------------------------------
1 | import pyodrx
2 | import numpy as np
3 | import os
4 |
5 | line1 = pyodrx.Line(100)
6 |
7 | arc1 = pyodrx.Arc(0.05,angle=np.pi/2)
8 | line2 = pyodrx.Line(100)
9 | arc2 = pyodrx.Arc(-0.05,angle=3*np.pi/4)
10 |
11 | cloth = pyodrx.Spiral(0.001,0.009,100)
12 |
13 | planview = pyodrx.PlanView()
14 |
15 |
16 | planview.add_geometry(line1)
17 |
18 | rm = pyodrx.RoadMark(pyodrx.RoadMarkType.solid,0.2,rule=pyodrx.MarkRule.no_passing)
19 |
20 |
21 | lane1 = pyodrx.Lane(a=2)
22 | lane1.add_roadmark(rm)
23 | lanesec = pyodrx.LaneSection(0,lane1)
24 |
25 | lane2 = pyodrx.Lane(a=4)
26 | lane2.add_roadmark(rm)
27 | lane3 = pyodrx.Lane(a=3)
28 | lane3.add_roadmark(rm)
29 | lane4 = pyodrx.Lane(a=3)
30 | lane4.add_roadmark(rm)
31 | lane5 = pyodrx.Lane(a=3)
32 | lane5.add_roadmark(rm)
33 |
34 | lanesec.add_left_lane(lane2)
35 | lanesec.add_left_lane(lane3)
36 | lanesec.add_right_lane(lane4)
37 | lanesec.add_right_lane(lane5)
38 |
39 | lanes = pyodrx.Lanes()
40 | lanes.add_lanesection(lanesec)
41 |
42 |
43 | road = pyodrx.Road(1,planview,lanes)
44 |
45 | odr = pyodrx.OpenDrive('myroad')
46 |
47 | odr.add_road(road)
48 |
49 | odr.adjust_roads_and_lanes()
50 |
51 | pyodrx.run_road(odr,os.path.join('..','esmini'))
--------------------------------------------------------------------------------
/examples/full_junction.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import os
3 |
4 | import pyodrx
5 |
6 |
7 |
8 |
9 | roads = []
10 | numintersections = 4 # 3 or 4
11 | angles = []
12 | for i in range(numintersections):
13 | roads.append(pyodrx.create_straight_road(i))
14 | # use this instead to change the number of lanes in the crossing
15 | #roads.append(pyodrx.generators.create_straight_road(i, length=100, junction=-1, n_lanes=2, lane_offset=3))
16 | angles.append(i * 2*np.pi/numintersections)
17 |
18 | # use this for a T-crossing instead
19 | # angles = [0,np.pi/2, 3*np.pi/2]
20 |
21 | print(roads)
22 | junc = pyodrx.create_junction_roads(roads,angles,8)
23 |
24 | odr = pyodrx.OpenDrive('myroad')
25 | junction = pyodrx.create_junction(junc,1,roads)
26 |
27 | odr.add_junction(junction)
28 | for r in roads:
29 | odr.add_road(r)
30 | for j in junc:
31 | odr.add_road(j)
32 |
33 | odr.adjust_roads_and_lanes()
34 |
35 | # write the OpenDRIVE file as xodr using current script name
36 | odr.write_xml(os.path.basename(__file__).replace('.py','.xodr'))
37 |
38 | # uncomment the following line to display the road using esmini
39 | # pyodrx.run_road(odr,os.path.join('..','..','esmini'))
--------------------------------------------------------------------------------
/examples/highway_example.py:
--------------------------------------------------------------------------------
1 | import pyodrx
2 | import os
3 |
4 | # create some simple roads
5 | roads= []
6 | # start road
7 | roads.append(pyodrx.create_road([pyodrx.Spiral(-0.004,0.00001,100), pyodrx.Spiral(0.00001,0.005,50), pyodrx.Arc(0.005,50)],id =0,left_lanes=3,right_lanes=4))
8 | # intermittent road
9 | roads.append(pyodrx.create_road([pyodrx.Spiral(0.0001,0.003,65), pyodrx.Spiral(0.003,0.00001,50) ],id =1,left_lanes=3,right_lanes=3))
10 |
11 |
12 | #exit road
13 | roads.append(pyodrx.create_road(pyodrx.Line(50),id =2,left_lanes=0,right_lanes=1))
14 | # junctions for exit
15 | roads.append(pyodrx.create_road(pyodrx.Spiral(0.005,0.0001,50),id =3,left_lanes=3,right_lanes=3,road_type=1)) # continue
16 | roads.append(pyodrx.create_road(pyodrx.Spiral(0.005,-0.02,100),id =4,left_lanes=0,right_lanes=1,road_type=1)) # exit
17 |
18 | # final road
19 | roads.append(pyodrx.create_road([pyodrx.Spiral(-0.00001,-0.003,45),pyodrx.Arc(-0.003,60)],id =5,left_lanes=2,right_lanes=3))
20 |
21 | # entry junction
22 | roads.append(pyodrx.create_road([pyodrx.Line(30) ],id =6,left_lanes=2,right_lanes=3,road_type=2)) # continue
23 | roads.append(pyodrx.create_road([pyodrx.Spiral(0.004,0.000001,50) ],id =7,left_lanes=1,right_lanes=0,road_type=2)) # entry
24 |
25 | # entry road
26 | roads.append(pyodrx.create_road(pyodrx.Arc(0.004,60),id =8,left_lanes=1,right_lanes=0))
27 |
28 |
29 | # add predecessors and succesors to the non junction roads
30 | roads[0].add_successor(pyodrx.ElementType.junction,1)
31 | roads[1].add_predecessor(pyodrx.ElementType.junction,1)
32 | roads[1].add_successor(pyodrx.ElementType.junction,2)
33 | roads[2].add_predecessor(pyodrx.ElementType.junction,1)
34 |
35 | # add connections to the first junction road
36 | roads[3].add_predecessor(pyodrx.ElementType.road,0,pyodrx.ContactPoint.end)
37 | roads[3].add_successor(pyodrx.ElementType.road,1,pyodrx.ContactPoint.start)
38 |
39 | # add connections to the second junction road, the exit
40 | roads[4].add_predecessor(pyodrx.ElementType.road,0,pyodrx.ContactPoint.end,lane_offset=-3)
41 | roads[4].add_successor(pyodrx.ElementType.road,2,pyodrx.ContactPoint.start)
42 |
43 | # add connections to the final road
44 | roads[5].add_predecessor(pyodrx.ElementType.junction,2)
45 |
46 | # add connections to the junctionroad that continues
47 | roads[6].add_predecessor(pyodrx.ElementType.road,1,pyodrx.ContactPoint.end)
48 | roads[6].add_successor(pyodrx.ElementType.road,5,pyodrx.ContactPoint.start)
49 |
50 | # add connections to the entry junction road
51 | roads[7].add_predecessor(pyodrx.ElementType.road,1,pyodrx.ContactPoint.end,lane_offset=2)
52 | roads[7].add_successor(pyodrx.ElementType.road,8,pyodrx.ContactPoint.start)
53 |
54 | # add connection to the entry road
55 | roads[8].add_predecessor(pyodrx.ElementType.junction,2)
56 |
57 | # create the junction struct
58 | exit_junction = pyodrx.create_junction(roads[3:5],1,roads[0:3])
59 | entry_junction = pyodrx.create_junction(roads[6:8],2,[roads[x] for x in [1,5,8]])
60 | # create the opendrive
61 | odr = pyodrx.OpenDrive('myroad')
62 | for r in roads:
63 | odr.add_road(r)
64 | odr.adjust_roads_and_lanes()
65 | odr.add_junction(exit_junction)
66 | odr.add_junction(entry_junction)
67 |
68 | # write the OpenDRIVE file as xodr using current script name
69 | odr.write_xml(os.path.basename(__file__).replace('.py','.xodr'))
70 |
71 | # uncomment the following line to display the road using esmini
72 | # pyodrx.run_road(odr,os.path.join('..','..','esmini'))
--------------------------------------------------------------------------------
/examples/junction_trippel_twoway.py:
--------------------------------------------------------------------------------
1 | import pyodrx
2 | import numpy as np
3 | import os
4 |
5 |
6 |
7 | rm = pyodrx.RoadMark(pyodrx.RoadMarkType.solid,0.2)
8 |
9 | # create geometries
10 |
11 | geoms = []
12 | geoms.append(pyodrx.Line(100))
13 | geoms.append(pyodrx.Spiral(0.001,0.019,30))
14 | geoms.append(pyodrx.Line(100))
15 | geoms.append(pyodrx.Spiral(-0.001,-0.1,30))
16 | geoms.append(pyodrx.Line(100))
17 | geoms.append(pyodrx.Line(20))
18 | geoms.append(pyodrx.Line(100))
19 | numberofroads = len(geoms)
20 |
21 | # create planviews
22 | planviews = []
23 | for g in geoms:
24 | pv = pyodrx.PlanView()
25 | pv.add_geometry(g)
26 | planviews.append(pv)
27 |
28 |
29 |
30 | # create centerlanes
31 | lanecenters = []
32 | for i in range(numberofroads):
33 | lc = pyodrx.Lane(a=3)
34 | lc.add_roadmark(rm)
35 | lanecenters.append(lc)
36 |
37 | # create lanes
38 | rightlanes = []
39 | leftlanes = []
40 | for i in range(numberofroads):
41 | right = pyodrx.Lane(a=3)
42 | right.add_roadmark(rm)
43 | rightlanes.append(right)
44 | left = pyodrx.Lane(a=3)
45 | left.add_roadmark(rm)
46 | leftlanes.append(left)
47 |
48 | # create lanesections
49 | lanesections = []
50 | for i in range(numberofroads):
51 | lsec = pyodrx.LaneSection(0,lanecenters[i])
52 | lsec.add_right_lane(rightlanes[i])
53 | lsec.add_left_lane(leftlanes[i])
54 | lanesections.append(lsec)
55 |
56 | ## create lanes
57 | lanes = []
58 | for l in lanesections:
59 | lanes1 = pyodrx.Lanes()
60 | lanes1.add_lanesection(l)
61 | lanes.append(lanes1)
62 |
63 |
64 | # finally create the roads
65 | roads = []
66 | roadtypes = [-1,1,-1,1,-1,1,-1]
67 | for i in range(numberofroads):
68 | roads.append(pyodrx.Road(i,planviews[i],lanes[i],road_type=roadtypes[i]))
69 |
70 | roads[0].add_successor(pyodrx.ElementType.junction,1)
71 |
72 | roads[1].add_predecessor(pyodrx.ElementType.road,0,pyodrx.ContactPoint.end)
73 | roads[1].add_successor(pyodrx.ElementType.road,2,pyodrx.ContactPoint.start)
74 |
75 | roads[2].add_predecessor(pyodrx.ElementType.junction,1)
76 |
77 | roads[3].add_predecessor(pyodrx.ElementType.road,0,pyodrx.ContactPoint.end)
78 | roads[3].add_successor(pyodrx.ElementType.road,4,pyodrx.ContactPoint.start)
79 |
80 | roads[4].add_predecessor(pyodrx.ElementType.junction,1)
81 |
82 | roads[5].add_predecessor(pyodrx.ElementType.road,0,pyodrx.ContactPoint.end)
83 | roads[5].add_successor(pyodrx.ElementType.road,6,pyodrx.ContactPoint.start)
84 |
85 | roads[6].add_predecessor(pyodrx.ElementType.junction,1)
86 |
87 | # create the opendrive
88 | odr = pyodrx.OpenDrive('myroad')
89 | for r in roads:
90 | odr.add_road(r)
91 |
92 | # create junction
93 | junction = pyodrx.Junction('test',1)
94 | con1 = pyodrx.Connection(0,1,pyodrx.ContactPoint.start)
95 | con1.add_lanelink(-1,-1)
96 | con2 = pyodrx.Connection(0,3,pyodrx.ContactPoint.start)
97 | con2.add_lanelink(-1,-1)
98 | con3 = pyodrx.Connection(0,5,pyodrx.ContactPoint.start)
99 | con3.add_lanelink(-1,-1)
100 |
101 | con4 = pyodrx.Connection(2,1,pyodrx.ContactPoint.end)
102 | con4.add_lanelink(1,1)
103 | con5 = pyodrx.Connection(4,3,pyodrx.ContactPoint.end)
104 | con5.add_lanelink(1,1)
105 | con6 = pyodrx.Connection(6,5,pyodrx.ContactPoint.end)
106 | con6.add_lanelink(1,1)
107 |
108 | junction.add_connection(con1)
109 | junction.add_connection(con2)
110 | junction.add_connection(con3)
111 | junction.add_connection(con4)
112 | junction.add_connection(con5)
113 | junction.add_connection(con6)
114 |
115 | # odr.create_junction()
116 | odr.add_junction(junction)
117 | odr.adjust_roads_and_lanes()
118 | # pyodrx.prettyprint(odr.get_element())
119 |
120 | # write the OpenDRIVE file as xodr using current script name
121 | odr.write_xml(os.path.basename(__file__).replace('.py','.xodr'))
122 |
123 | # uncomment the following line to display the road using esmini
124 | # pyodrx.run_road(odr,os.path.join('..','..','esmini'))
--------------------------------------------------------------------------------
/examples/junction_with_signals.py:
--------------------------------------------------------------------------------
1 | # Same approach to creating a junction as "full_junction.py" but with signals for each incoming road.
2 | import numpy as np
3 | import os
4 | import pyodrx
5 | #import pyoscx
6 |
7 | roads = []
8 | incoming_roads = 4
9 | angles = []
10 | for i in range(incoming_roads):
11 | roads.append(pyodrx.create_straight_road(i))
12 | # use this instead to change the number of lanes in the crossing
13 | # roads.append(pyodrx.generators.create_straight_road(i, length=100, junction=-1, n_lanes=2, lane_offset=3))
14 | angles.append(i * 2 * np.pi / incoming_roads)
15 | if angles[-1] == 0:
16 | roads[-1].add_signal(pyodrx.Signal(s=98.0, t=-4, country="USA", Type="R1", subtype="1"))
17 | else:
18 | roads[-1].add_signal(pyodrx.Signal(s=2.0, t=4, country="USA", Type="R1", subtype="1", orientation=pyodrx.Orientation.negative))
19 |
20 |
21 |
22 | # use this for a T-crossing instead
23 | # angles = [0,np.pi/2, 3*np.pi/2]
24 |
25 | print(roads)
26 | junc = pyodrx.create_junction_roads(roads, angles, 8)
27 | odr = pyodrx.OpenDrive('myroad')
28 | junction = pyodrx.create_junction(junc, 1, roads)
29 |
30 | odr.add_junction(junction)
31 | for r in roads:
32 | odr.add_road(r)
33 | for j in junc:
34 | odr.add_road(j)
35 |
36 | odr.adjust_roads_and_lanes()
37 |
38 | # write the OpenDRIVE file as xodr using current script name
39 | odr.write_xml(os.path.basename(__file__).replace('.py','.xodr'))
40 |
41 | # uncomment the following line to display the road using esmini
42 | # pyodrx.run_road(odr,os.path.join('..','..','esmini'))
--------------------------------------------------------------------------------
/examples/lane_number_change_merge.py:
--------------------------------------------------------------------------------
1 | import pyodrx
2 | import os
3 |
4 | # create the planview and the geometry
5 | planview = pyodrx.PlanView()
6 |
7 |
8 | planview.add_geometry(pyodrx.Line(500))
9 |
10 |
11 | # create two different roadmarkings
12 | rm_solid = pyodrx.RoadMark(pyodrx.RoadMarkType.solid,0.2)
13 | rm_dashed = pyodrx.RoadMark(pyodrx.RoadMarkType.broken,0.2)
14 |
15 | # create a centerlane (same centerlane can be used since no linking is needed for this)
16 | centerlane = pyodrx.Lane(a=2)
17 | centerlane.add_roadmark(rm_solid)
18 |
19 | # create the first lanesection with two lanes
20 | lanesec1 = pyodrx.LaneSection(0,centerlane)
21 | lane1 = pyodrx.Lane(a=3)
22 | lane1.add_roadmark(rm_dashed)
23 |
24 | lane2 = pyodrx.Lane(a=3)
25 | lane2.add_roadmark(rm_solid)
26 |
27 | lanesec1.add_right_lane(lane1)
28 | lanesec1.add_right_lane(lane2)
29 |
30 | # create the second lanesection with one lane merging
31 | lanesec2 = pyodrx.LaneSection(250,centerlane)
32 | lane3 = pyodrx.Lane(a=3)
33 | lane3.add_roadmark(rm_dashed)
34 |
35 | lane4 = pyodrx.Lane(a=3,b=-0.1)
36 | lane4.add_roadmark(rm_solid)
37 |
38 | lanesec2.add_right_lane(lane3)
39 | lanesec2.add_right_lane(lane4)
40 |
41 | # create the last lanesection with one lane
42 | lanesec3 = pyodrx.LaneSection(280,centerlane)
43 |
44 | lane5 = pyodrx.Lane(a=3)
45 | lane5.add_roadmark(rm_solid)
46 |
47 | lanesec3.add_right_lane(lane5)
48 |
49 | # create the lane links
50 | lanelinker = pyodrx.LaneLinker()
51 | lanelinker.add_link(predlane=lane1,succlane=lane3)
52 | lanelinker.add_link(predlane=lane2,succlane=lane4)
53 | lanelinker.add_link(predlane=lane3,succlane=lane5)
54 |
55 | # create the lanes with the correct links
56 | lanes = pyodrx.Lanes()
57 | lanes.add_lanesection(lanesec1,lanelinker)
58 | lanes.add_lanesection(lanesec2,lanelinker)
59 | lanes.add_lanesection(lanesec3,lanelinker)
60 |
61 | # create the road
62 | road = pyodrx.Road(1,planview,lanes)
63 |
64 | # create the opendrive
65 | odr = pyodrx.OpenDrive('myroad')
66 | odr.add_road(road)
67 |
68 | # adjust the roads and lanes
69 | odr.adjust_roads_and_lanes()
70 |
71 | # write the OpenDRIVE file as xodr using current script name
72 | odr.write_xml(os.path.basename(__file__).replace('.py','.xodr'))
73 |
74 | # uncomment the following line to display the road using esmini
75 | # pyodrx.run_road(odr,os.path.join('..','..','esmini'))
--------------------------------------------------------------------------------
/examples/multiple_geometries_one_road.py:
--------------------------------------------------------------------------------
1 | import pyodrx
2 | import numpy as np
3 | import os
4 |
5 | ## EXAMPLE 1
6 | ## Multiple geometries in one only road.
7 |
8 | ##1. Create the planview
9 | planview = pyodrx.PlanView()
10 |
11 | ##2. Create some geometries and add them to the planview
12 | line1 = pyodrx.Line(100)
13 | arc1 = pyodrx.Arc(0.05,angle=np.pi/2)
14 | line2 = pyodrx.Line(100)
15 | cloth1 = pyodrx.Spiral(0.05,-0.1,30)
16 | line3 = pyodrx.Line(100)
17 |
18 | planview.add_geometry(line1)
19 | planview.add_geometry(arc1)
20 | planview.add_geometry(line2)
21 | planview.add_geometry(cloth1)
22 | planview.add_geometry(line3)
23 |
24 |
25 | ##3. Create a solid roadmark
26 | rm = pyodrx.RoadMark(pyodrx.RoadMarkType.solid,0.2)
27 |
28 | ##4. Create centerlane
29 | centerlane = pyodrx.Lane(a=2)
30 | centerlane.add_roadmark(rm)
31 |
32 | ##5. Create lane section form the centerlane
33 | lanesec = pyodrx.LaneSection(0,centerlane)
34 |
35 | ##6. Create left and right lanes
36 | lane2 = pyodrx.Lane(a=3)
37 | lane2.add_roadmark(rm)
38 | lane3 = pyodrx.Lane(a=3)
39 | lane3.add_roadmark(rm)
40 |
41 | ##7. Add lanes to lane section
42 | lanesec.add_left_lane(lane2)
43 | lanesec.add_right_lane(lane3)
44 |
45 | ##8. Add lane section to Lanes
46 | lanes = pyodrx.Lanes()
47 | lanes.add_lanesection(lanesec)
48 |
49 | ##9. Create Road from Planview and Lanes
50 | road = pyodrx.Road(1,planview,lanes)
51 |
52 | ##10. Create the OpenDrive class (Master class)
53 | odr = pyodrx.OpenDrive('myroad')
54 |
55 | ##11. Finally add roads to Opendrive
56 | odr.add_road(road)
57 |
58 | ##12. Adjust initial positions of the roads looking at succ-pred logic
59 | odr.adjust_roads_and_lanes()
60 |
61 | ##13. Print the .xodr file
62 | pyodrx.prettyprint(odr.get_element())
63 |
64 | # write the OpenDRIVE file as xodr using current script name
65 | odr.write_xml(os.path.basename(__file__).replace('.py','.xodr'))
66 |
67 | # uncomment the following line to display the road using esmini
68 | # pyodrx.run_road(odr,os.path.join('..','..','esmini'))
--------------------------------------------------------------------------------
/examples/multiple_geometries_one_road_with_objects.py:
--------------------------------------------------------------------------------
1 | import pyodrx
2 | import numpy as np
3 | import os
4 | ## EXAMPLE 1
5 | ## Multiple geometries in one only road. Additionally adding objects.
6 |
7 | ##1. Create the planview
8 | planview = pyodrx.PlanView()
9 |
10 | ##2. Create some geometries and add them to the planview
11 | line1 = pyodrx.Line(100)
12 | arc1 = pyodrx.Arc(0.05,angle=np.pi/2)
13 | line2 = pyodrx.Line(100)
14 | cloth1 = pyodrx.Spiral(0.05,-0.1,30)
15 | line3 = pyodrx.Line(100)
16 |
17 | planview.add_geometry(line1)
18 | planview.add_geometry(arc1)
19 | planview.add_geometry(line2)
20 | planview.add_geometry(cloth1)
21 | planview.add_geometry(line3)
22 |
23 |
24 | ##3. Create a solid roadmark
25 | rm = pyodrx.RoadMark(pyodrx.RoadMarkType.solid,0.2)
26 |
27 | ##4. Create centerlane
28 | centerlane = pyodrx.Lane(a=2)
29 | centerlane.add_roadmark(rm)
30 |
31 | ##5. Create lane section form the centerlane
32 | lanesec = pyodrx.LaneSection(0,centerlane)
33 |
34 | ##6. Create left and right lanes
35 | lane2 = pyodrx.Lane(a=3)
36 | lane2.add_roadmark(rm)
37 | lane3 = pyodrx.Lane(a=3)
38 | lane3.add_roadmark(rm)
39 |
40 | ##7. Add lanes to lane section
41 | lanesec.add_left_lane(lane2)
42 | lanesec.add_right_lane(lane3)
43 |
44 | ##8. Add lane section to Lanes
45 | lanes = pyodrx.Lanes()
46 | lanes.add_lanesection(lanesec)
47 |
48 | ##9. Create Road from Planview and Lanes
49 | road = pyodrx.Road(1,planview,lanes)
50 |
51 |
52 | ##10. Create the OpenDrive class (Master class)
53 | odr = pyodrx.OpenDrive('myroad')
54 |
55 | ##11. Finally add roads to Opendrive
56 | odr.add_road(road)
57 |
58 | ##12. Adjust initial positions of the roads looking at succ-pred logic
59 | odr.adjust_roads_and_lanes()
60 |
61 | ##13. After adjustment, repeating objects on side of the road can be added automatically
62 | guardrail = pyodrx.Object(0,0,height=0.3,zOffset=0.4,Type=pyodrx.ObjectType.barrier,name="guardRail")
63 | road.add_object_roadside(guardrail, 0, 0, tOffset = 0.8)
64 |
65 | delineator = pyodrx.Object(0,0,height=1,zOffset=0,Type=pyodrx.ObjectType.pole,name="delineator")
66 | road.add_object_roadside(delineator, 50, sOffset = 25, tOffset = 0.85)
67 |
68 | ##14. Add some other objects at specific positions
69 | #single emergency callbox
70 | emergencyCallbox = pyodrx.Object(30,-6,Type=pyodrx.ObjectType.pole,name="emergencyCallBox")
71 | road.add_object(emergencyCallbox)
72 |
73 | #repeating jersey barrier
74 | jerseyBarrier = pyodrx.Object(0,0,height=0.75,zOffset=0,Type=pyodrx.ObjectType.barrier,name="jerseyBarrier")
75 | jerseyBarrier.repeat(repeatLength=25,repeatDistance=0,sStart=240)
76 | road.add_object(jerseyBarrier)
77 |
78 | ##15. Print the .xodr file
79 | pyodrx.prettyprint(odr.get_element())
80 |
81 | # write the OpenDRIVE file as xodr using current script name
82 | odr.write_xml(os.path.basename(__file__).replace('.py','.xodr'))
83 |
84 | # uncomment the following line to display the road using esmini
85 | # pyodrx.run_road(odr,os.path.join('..','..','esmini'))
--------------------------------------------------------------------------------
/examples/road_merge.py:
--------------------------------------------------------------------------------
1 | import pyodrx
2 |
3 | import os
4 |
5 | # create some roads
6 | roads= []
7 | roads.append(pyodrx.create_road(pyodrx.Line(100),id = 0, left_lanes=1,right_lanes=2))
8 | roads.append(pyodrx.create_road(pyodrx.Line(100),id =1,left_lanes=0,right_lanes=1))
9 | roads.append(pyodrx.create_road(pyodrx.Line(100),id =2,left_lanes=1,right_lanes=3))
10 | roads.append(pyodrx.create_road(pyodrx.Spiral(0.001,0.02,30),id =3,left_lanes=1,right_lanes=2,road_type=1))
11 | roads.append(pyodrx.create_road(pyodrx.Spiral(-0.001,-0.02,30),id =4,left_lanes=0,right_lanes=1,road_type=1))
12 |
13 | # add some connections to non junction roads
14 | roads[0].add_successor(pyodrx.ElementType.junction,1)
15 | roads[1].add_successor(pyodrx.ElementType.junction,1)
16 | roads[2].add_predecessor(pyodrx.ElementType.junction,1)
17 |
18 | # add connections to the first connecting road
19 | roads[3].add_predecessor(pyodrx.ElementType.road,0,pyodrx.ContactPoint.end)
20 | roads[3].add_successor(pyodrx.ElementType.road,2,pyodrx.ContactPoint.start)
21 |
22 | # add connections to the second connecting road with an offset
23 | roads[4].add_predecessor(pyodrx.ElementType.road,1,pyodrx.ContactPoint.end)
24 | roads[4].add_successor(pyodrx.ElementType.road,2,pyodrx.ContactPoint.start,lane_offset=-2)
25 |
26 |
27 |
28 | junction = pyodrx.create_junction(roads[3:],1,roads[0:3])
29 |
30 |
31 | # create the opendrive
32 | odr = pyodrx.OpenDrive('myroad')
33 | for r in roads:
34 | odr.add_road(r)
35 | odr.adjust_roads_and_lanes()
36 | odr.add_junction(junction)
37 |
38 | # write the OpenDRIVE file as xodr using current script name
39 | odr.write_xml(os.path.basename(__file__).replace('.py','.xodr'))
40 |
41 | # uncomment the following line to display the road using esmini
42 | # pyodrx.run_road(odr,os.path.join('..','..','esmini'))
--------------------------------------------------------------------------------
/examples/road_merge_w_lane_merge.py:
--------------------------------------------------------------------------------
1 | import pyodrx
2 |
3 | import os
4 |
5 | # create some roads
6 | roads= []
7 |
8 | # create two simple roads to merge
9 | roads.append(pyodrx.create_road(pyodrx.Line(100),id = 0, left_lanes=0,right_lanes=2))
10 | roads.append(pyodrx.create_road(pyodrx.Line(100),id =1,left_lanes=0,right_lanes=1))
11 |
12 | # manually create the final road
13 |
14 |
15 | # create the planview and the geometry
16 | planview = pyodrx.PlanView()
17 | planview.add_geometry(pyodrx.Line(200))
18 |
19 | # create two different roadmarkings
20 | rm_solid = pyodrx.RoadMark(pyodrx.RoadMarkType.solid,0.2)
21 | rm_dashed = pyodrx.RoadMark(pyodrx.RoadMarkType.broken,0.2)
22 |
23 | # create a centerlane (same centerlane can be used since no linking is needed for this)
24 | centerlane = pyodrx.Lane(a=2)
25 | centerlane.add_roadmark(rm_solid)
26 |
27 | # create the first lanesection with three lanes
28 | lanesec1 = pyodrx.LaneSection(0,centerlane)
29 | lane1 = pyodrx.Lane(a=3)
30 | lane1.add_roadmark(rm_dashed)
31 |
32 | lane2 = pyodrx.Lane(a=3)
33 | lane2.add_roadmark(rm_dashed)
34 |
35 | lane3 = pyodrx.Lane(a=3)
36 | lane3.add_roadmark(rm_solid)
37 |
38 | lanesec1.add_right_lane(lane1)
39 | lanesec1.add_right_lane(lane2)
40 | lanesec1.add_right_lane(lane3)
41 |
42 | # create the second lanesection with one lane merging
43 | lanesec2 = pyodrx.LaneSection(70,centerlane)
44 | lane4 = pyodrx.Lane(a=3)
45 | lane4.add_roadmark(rm_dashed)
46 |
47 | lane5 = pyodrx.Lane(a=3)
48 | lane5.add_roadmark(rm_dashed)
49 |
50 | lane6 = pyodrx.Lane(a=3,b=-0.1)
51 | lane6.add_roadmark(rm_solid)
52 |
53 | lanesec2.add_right_lane(lane4)
54 | lanesec2.add_right_lane(lane5)
55 | lanesec2.add_right_lane(lane6)
56 |
57 | # create the last lanesection with one lane
58 | lanesec3 = pyodrx.LaneSection(100,centerlane)
59 |
60 | lane7 = pyodrx.Lane(a=3)
61 | lane7.add_roadmark(rm_dashed)
62 |
63 | lane8 = pyodrx.Lane(a=3)
64 | lane8.add_roadmark(rm_solid)
65 |
66 | lanesec3.add_right_lane(lane7)
67 | lanesec3.add_right_lane(lane8)
68 |
69 | # create the lane links
70 | lanelinker = pyodrx.LaneLinker()
71 | lanelinker.add_link(predlane=lane1,succlane=lane4)
72 | lanelinker.add_link(predlane=lane2,succlane=lane5)
73 | lanelinker.add_link(predlane=lane3,succlane=lane6)
74 |
75 | lanelinker.add_link(predlane=lane5,succlane=lane7)
76 | lanelinker.add_link(predlane=lane6,succlane=lane8)
77 |
78 | # create the lanes with the correct links
79 | lanes = pyodrx.Lanes()
80 | lanes.add_lanesection(lanesec1,lanelinker)
81 | lanes.add_lanesection(lanesec2,lanelinker)
82 | lanes.add_lanesection(lanesec3,lanelinker)
83 |
84 | # create the road
85 | roads.append(pyodrx.Road(2,planview,lanes))
86 |
87 |
88 | # create junction roads
89 | roads.append(pyodrx.create_road(pyodrx.Spiral(0.001,0.02,30),id =3,left_lanes=0,right_lanes=2,road_type=1))
90 | roads.append(pyodrx.create_road(pyodrx.Spiral(-0.001,-0.02,30),id =4,left_lanes=0,right_lanes=1,road_type=1))
91 |
92 | # add some connections to non junction roads
93 | roads[0].add_successor(pyodrx.ElementType.junction,1)
94 | roads[1].add_successor(pyodrx.ElementType.junction,1)
95 | roads[2].add_predecessor(pyodrx.ElementType.junction,1)
96 |
97 | # add connections to the first connecting road
98 | roads[3].add_predecessor(pyodrx.ElementType.road,0,pyodrx.ContactPoint.end)
99 | roads[3].add_successor(pyodrx.ElementType.road,2,pyodrx.ContactPoint.start)
100 |
101 | # add connections to the second connecting road with an offset
102 | roads[4].add_predecessor(pyodrx.ElementType.road,1,pyodrx.ContactPoint.end)
103 | roads[4].add_successor(pyodrx.ElementType.road,2,pyodrx.ContactPoint.start,lane_offset=-2)
104 |
105 |
106 |
107 | junction = pyodrx.create_junction(roads[3:],1,roads[0:3])
108 |
109 |
110 | # create the opendrive
111 | odr = pyodrx.OpenDrive('myroad')
112 | for r in roads:
113 | odr.add_road(r)
114 | odr.adjust_roads_and_lanes()
115 | odr.add_junction(junction)
116 |
117 | # write the OpenDRIVE file as xodr using current script name
118 | odr.write_xml(os.path.basename(__file__).replace('.py','.xodr'))
119 |
120 | # uncomment the following line to display the road using esmini
121 | # pyodrx.run_road(odr,os.path.join('..','..','esmini'))
--------------------------------------------------------------------------------
/examples/road_split.py:
--------------------------------------------------------------------------------
1 | import pyodrx
2 | import os
3 |
4 | # create some simple roads
5 | roads= []
6 | roads.append(pyodrx.create_road(pyodrx.Line(100),id =0,left_lanes=0,right_lanes=2))
7 | roads.append(pyodrx.create_road(pyodrx.Line(100),id =1,left_lanes=0,right_lanes=1))
8 | roads.append(pyodrx.create_road(pyodrx.Line(100),id =2,left_lanes=0,right_lanes=1))
9 | roads.append(pyodrx.create_road(pyodrx.Spiral(0.001,0.02,30),id =3,left_lanes=0,right_lanes=1,road_type=1))
10 | roads.append(pyodrx.create_road(pyodrx.Spiral(-0.001,-0.02,30),id =4,left_lanes=0,right_lanes=1,road_type=1))
11 |
12 | # add predecessors and succesors to the non junction roads
13 | roads[0].add_successor(pyodrx.ElementType.junction,1)
14 | roads[1].add_predecessor(pyodrx.ElementType.junction,1)
15 | roads[2].add_predecessor(pyodrx.ElementType.junction,1)
16 |
17 | # add connections to the first junction road
18 | roads[3].add_predecessor(pyodrx.ElementType.road,0,pyodrx.ContactPoint.end)
19 | roads[3].add_successor(pyodrx.ElementType.road,1,pyodrx.ContactPoint.start)
20 |
21 | # add connections to the second junction road, together with an offset
22 | roads[4].add_predecessor(pyodrx.ElementType.road,0,pyodrx.ContactPoint.end,lane_offset=-1)
23 | roads[4].add_successor(pyodrx.ElementType.road,2,pyodrx.ContactPoint.start)
24 |
25 | # create the junction struct
26 | junction = pyodrx.create_junction(roads[3:],1,roads[0:3])
27 |
28 | # create the opendrive
29 | odr = pyodrx.OpenDrive('myroad')
30 | for r in roads:
31 | odr.add_road(r)
32 | odr.adjust_roads_and_lanes()
33 | odr.add_junction(junction)
34 |
35 | # write the OpenDRIVE file as xodr using current script name
36 | odr.write_xml(os.path.basename(__file__).replace('.py','.xodr'))
37 |
38 | # uncomment the following line to display the road using esmini
39 | # pyodrx.run_road(odr,os.path.join('..','..','esmini'))
--------------------------------------------------------------------------------
/examples/road_split_w_lane_split.py:
--------------------------------------------------------------------------------
1 | import pyodrx
2 | import os
3 |
4 | # create some simple roads
5 | roads= []
6 |
7 | # create the planview and the geometry
8 | planview = pyodrx.PlanView()
9 | planview.add_geometry(pyodrx.Line(200))
10 |
11 |
12 | # create two different roadmarkings
13 | rm_solid = pyodrx.RoadMark(pyodrx.RoadMarkType.solid,0.2,
14 | rm_dashed = pyodrx.RoadMark(pyodrx.RoadMarkType.broken,0.2)
15 |
16 |
17 | # create a centerlane (same centerlane can be used since no linking is needed for this)
18 | centerlane = pyodrx.Lane(a=2)
19 | centerlane.add_roadmark(rm_solid)
20 |
21 | # create first lanesection with two lanes
22 | lanesec1 = pyodrx.LaneSection(0,centerlane)
23 | lane0 = pyodrx.Lane(a=3)
24 | lane0.add_roadmark(rm_dashed)
25 | lane1 = pyodrx.Lane(a=3)
26 | lane1.add_roadmark(rm_solid)
27 |
28 | lanesec1.add_right_lane(lane0)
29 | lanesec1.add_right_lane(lane1)
30 |
31 | # create the second lanesection with a third lane emerging
32 | lanesec2 = pyodrx.LaneSection(100,centerlane)
33 | lane2 = pyodrx.Lane(a=3)
34 | lane2.add_roadmark(rm_dashed)
35 |
36 | lane3 = pyodrx.Lane(a=3)
37 | lane3.add_roadmark(rm_dashed)
38 |
39 | lane4 = pyodrx.Lane(a=0,b=0.1)
40 | lane4.add_roadmark(rm_solid)
41 |
42 | lanesec2.add_right_lane(lane2)
43 | lanesec2.add_right_lane(lane3)
44 | lanesec2.add_right_lane(lane4)
45 |
46 | # create the last lanesection with two paralell lanes
47 | lanesec3 = pyodrx.LaneSection(130,centerlane)
48 | lane5 = pyodrx.Lane(a=3)
49 | lane5.add_roadmark(rm_dashed)
50 |
51 | lane6 = pyodrx.Lane(a=3)
52 | lane6.add_roadmark(rm_dashed)
53 |
54 | lane7 = pyodrx.Lane(a=3)
55 | lane7.add_roadmark(rm_solid)
56 |
57 | lanesec3.add_right_lane(lane5)
58 | lanesec3.add_right_lane(lane6)
59 | lanesec3.add_right_lane(lane7)
60 |
61 | # create the lane links
62 | lanelinker = pyodrx.LaneLinker()
63 | lanelinker.add_link(predlane=lane0,succlane=lane2)
64 | lanelinker.add_link(predlane=lane1,succlane=lane3)
65 | lanelinker.add_link(predlane=lane2,succlane=lane5)
66 | lanelinker.add_link(predlane=lane3,succlane=lane6)
67 | lanelinker.add_link(predlane=lane4,succlane=lane7)
68 |
69 | # create the lanes with the correct links
70 | lanes = pyodrx.Lanes()
71 | lanes.add_lanesection(lanesec1,lanelinker)
72 | lanes.add_lanesection(lanesec2,lanelinker)
73 | lanes.add_lanesection(lanesec3,lanelinker)
74 |
75 | # create the road
76 | roads.append(pyodrx.Road(0,planview,lanes))
77 |
78 | # create the other roads
79 | roads.append(pyodrx.create_road(pyodrx.Line(100),id =1,left_lanes=0,right_lanes=2))
80 | roads.append(pyodrx.create_road(pyodrx.Line(100),id =2,left_lanes=0,right_lanes=1))
81 | # create the junction roads
82 | roads.append(pyodrx.create_road(pyodrx.Spiral(0.001,0.02,30),id =3,left_lanes=0,right_lanes=2,road_type=1))
83 | roads.append(pyodrx.create_road(pyodrx.Spiral(-0.001,-0.02,30),id =4,left_lanes=0,right_lanes=1,road_type=1))
84 |
85 | # add predecessors and succesors to the non junction roads
86 | roads[0].add_successor(pyodrx.ElementType.junction,1)
87 | roads[1].add_predecessor(pyodrx.ElementType.junction,1)
88 | roads[2].add_predecessor(pyodrx.ElementType.junction,1)
89 |
90 | # add connections to the first junction road
91 | roads[3].add_predecessor(pyodrx.ElementType.road,0,pyodrx.ContactPoint.end)
92 | roads[3].add_successor(pyodrx.ElementType.road,1,pyodrx.ContactPoint.start)
93 |
94 | # add connections to the second junction road, together with an offset
95 | roads[4].add_predecessor(pyodrx.ElementType.road,0,pyodrx.ContactPoint.end,lane_offset=-2)
96 | roads[4].add_successor(pyodrx.ElementType.road,2,pyodrx.ContactPoint.start)
97 |
98 | # create the junction struct
99 | junction = pyodrx.create_junction(roads[3:],1,roads[0:3])
100 |
101 | # create the opendrive
102 | odr = pyodrx.OpenDrive('myroad')
103 | for r in roads:
104 | odr.add_road(r)
105 | odr.adjust_roads_and_lanes()
106 | odr.add_junction(junction)
107 |
108 | # write the OpenDRIVE file as xodr using current script name
109 | odr.write_xml(os.path.basename(__file__).replace('.py','.xodr'))
110 |
111 | # uncomment the following line to display the road using esmini
112 | # pyodrx.run_road(odr,os.path.join('..','..','esmini'))
--------------------------------------------------------------------------------
/examples/two_roads.py:
--------------------------------------------------------------------------------
1 | import pyodrx
2 | import numpy as np
3 | import os
4 |
5 |
6 | odr = pyodrx.OpenDrive('myroad')
7 |
8 | #---------------- Road 1
9 | planview = pyodrx.PlanView(0,0,0)
10 |
11 | # create some geometries and add to the planview
12 | planview.add_geometry(pyodrx.Line(100))
13 |
14 | # create a solid roadmark
15 | rm = pyodrx.RoadMark(pyodrx.RoadMarkType.solid, 0.2)
16 |
17 | # create centerlane
18 | centerlane_1 = pyodrx.Lane(a=2)
19 | centerlane_1.add_roadmark(rm)
20 | lanesec_1 = pyodrx.LaneSection(0,centerlane_1)
21 |
22 | # add a driving lane
23 | lane2_1 = pyodrx.Lane(a=3.1)
24 | lane2_1.add_roadmark(rm)
25 | lanesec_1.add_left_lane(lane2_1)
26 |
27 | lane3_1 = pyodrx.Lane(a=3.1)
28 | lane3_1.add_roadmark(rm)
29 | lanesec_1.add_right_lane(lane3_1)
30 |
31 | ## finalize the road
32 | lanes_1 = pyodrx.Lanes()
33 | lanes_1.add_lanesection(lanesec_1)
34 |
35 | road = pyodrx.Road(1,planview,lanes_1)
36 |
37 |
38 | odr.add_road(road)
39 |
40 |
41 | #---------------- Road 2
42 |
43 | planview2 = pyodrx.PlanView(x_start = 0, y_start = 10,h_start=np.pi/2)
44 | # planview2 = pyodrx.PlanView()
45 |
46 | # create some geometries and add to the planview
47 | planview2.add_geometry(pyodrx.Line(200))
48 |
49 | # create a solid roadmark
50 | rm = pyodrx.RoadMark(pyodrx.RoadMarkType.solid, 0.2)
51 |
52 | # create centerlane
53 | centerlane = pyodrx.Lane(a=2)
54 | centerlane.add_roadmark(rm)
55 | lanesec = pyodrx.LaneSection(0,centerlane)
56 |
57 | # add a driving lane
58 | lane2 = pyodrx.Lane(a=3.1)
59 | lane2.add_roadmark(rm)
60 | lanesec.add_left_lane(lane2)
61 |
62 | lane3 = pyodrx.Lane(a=3.1)
63 | lane3.add_roadmark(rm)
64 | lanesec.add_right_lane(lane3)
65 |
66 | ## finalize the road
67 | lanes = pyodrx.Lanes()
68 | lanes.add_lanesection(lanesec)
69 |
70 | road2 = pyodrx.Road(2,planview2,lanes)
71 |
72 | odr.add_road(road2)
73 |
74 |
75 |
76 |
77 | #------------------ Finalize
78 | odr.adjust_roads_and_lanes()
79 | pyodrx.prettyprint(odr.get_element())
80 |
81 | # write the OpenDRIVE file as xodr using current script name
82 | odr.write_xml(os.path.basename(__file__).replace('.py','.xodr'))
83 |
84 | # uncomment the following line to display the road using esmini
85 | # pyodrx.run_road(odr,os.path.join('..','..','esmini'))
86 |
--------------------------------------------------------------------------------
/html/pyodrx/exceptions.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
class NotSameAmountOfLanesError(Exception):
30 | """ Raised when the amount of Lanes are not the same (used for the automation of linking)
31 | """
32 | pass
33 |
34 | class NotEnoughInputArguments(Exception):
35 | """ Raised when one of the needed "optional" inputs are not used
36 | """
37 | pass
38 |
39 | class ToManyOptionalArguments(Exception):
40 | """ Raised when one of the needed "optional" inputs are not used
41 | """
42 | pass
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
Classes
53 |
54 |
55 | class NotEnoughInputArguments
56 | (*args, **kwargs)
57 |
58 |
59 |
Raised when one of the needed "optional" inputs are not used
60 |
61 |
62 | Expand source code
63 |
64 |
class NotEnoughInputArguments(Exception):
65 | """ Raised when one of the needed "optional" inputs are not used
66 | """
67 | pass
68 |
69 |
Ancestors
70 |
71 |
builtins.Exception
72 |
builtins.BaseException
73 |
74 |
75 |
76 | class NotSameAmountOfLanesError
77 | (*args, **kwargs)
78 |
79 |
80 |
Raised when the amount of Lanes are not the same (used for the automation of linking)
81 |
82 |
83 | Expand source code
84 |
85 |
class NotSameAmountOfLanesError(Exception):
86 | """ Raised when the amount of Lanes are not the same (used for the automation of linking)
87 | """
88 | pass
89 |
90 |
Ancestors
91 |
92 |
builtins.Exception
93 |
builtins.BaseException
94 |
95 |
96 |
97 | class ToManyOptionalArguments
98 | (*args, **kwargs)
99 |
100 |
101 |
Raised when one of the needed "optional" inputs are not used
102 |
103 |
104 | Expand source code
105 |
106 |
class ToManyOptionalArguments(Exception):
107 | """ Raised when one of the needed "optional" inputs are not used
108 | """
109 | pass
import xml.etree.ElementTree as ET
30 | import xml.dom.minidom as mini
31 |
32 |
33 | import os
34 |
35 |
36 | def run_road(opendrive,esminipath = 'esmini'):
37 | """ write a scenario and runs it in esminis OpenDriveViewer with some random traffic
38 | Parameters
39 | ----------
40 | opendrive (OpenDrive): the pyodrx road to run
41 |
42 | esminipath (str): the path to esmini
43 | Default: pyoscx
44 |
45 | """
46 | _scenariopath = os.path.join(esminipath,'resources','xodr')
47 | print(_scenariopath)
48 | opendrive.write_xml(os.path.join(_scenariopath,'pythonroad.xodr'),True)
49 |
50 | if os.name == 'posix':
51 | os.system(os.path.join('.', esminipath, 'bin','odrviewer') + ' --odr ' + os.path.join(esminipath,'resources','xodr','pythonroad.xodr') + ' --osi_features on --clear-color 0.2,0.2,0.2 --window 50 50 800 400 --density 15' )
52 | elif os.name == 'nt':
53 | os.system(os.path.join(esminipath,'bin','odrviewer.exe') + ' --odr ' + os.path.join(esminipath,'resources','xodr','pythonroad.xodr') + ' --osi_features on --clear-color 0.2,0.2,0.2 --window 50 50 800 400 --density 15' )
54 |
55 |
56 | def enum2str(enum):
57 | """ helper to create strings from enums that should contain space but have to have _
58 |
59 | Parameters
60 | ----------
61 | enum (Enum): a enum of pyodrx
62 |
63 | Returns
64 | -------
65 | enumstr (str): the enum as a string replacing _ with ' '
66 |
67 | """
68 | return enum.name.replace('_',' ')
69 |
70 | def prettyprint(element):
71 | """ prints the element to the commandline
72 |
73 | Parameters
74 | ----------
75 | element (Element): element to print
76 |
77 | """
78 | rough = ET.tostring(element,'utf-8')
79 | reparsed = mini.parseString(rough)
80 | print(reparsed.toprettyxml(indent="\t"))
81 |
82 |
83 | def printToFile(element,filename,prettyprint=True):
84 | """ prints the element to a xml file
85 |
86 | Parameters
87 | ----------
88 | element (Element): element to print
89 |
90 | filename (str): file to save to
91 |
92 | prettyprint (bool): pretty or "ugly" print
93 |
94 | """
95 | if prettyprint:
96 | rough = ET.tostring(element,'utf-8').replace(b'\n',b'').replace(b'\t',b'')
97 | reparsed = mini.parseString(rough)
98 | towrite = reparsed.toprettyxml(indent="\t")
99 | with open(filename,"w") as file_handle:
100 | file_handle.write(towrite)
101 | else:
102 | tree = ET.ElementTree(element)
103 | with open(filename,"wb") as file_handle:
104 | tree.write(file_handle)
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
Functions
113 |
114 |
115 | def enum2str(enum)
116 |
117 |
118 |
helper to create strings from enums that should contain space but have to have _
119 |
Parameters
120 |
enum (Enum): a enum of pyodrx
121 |
122 |
Returns
123 |
enumstr (str): the enum as a string replacing _ with ' '
124 |
125 |
126 |
127 | Expand source code
128 |
129 |
def enum2str(enum):
130 | """ helper to create strings from enums that should contain space but have to have _
131 |
132 | Parameters
133 | ----------
134 | enum (Enum): a enum of pyodrx
135 |
136 | Returns
137 | -------
138 | enumstr (str): the enum as a string replacing _ with ' '
139 |
140 | """
141 | return enum.name.replace('_',' ')
142 |
143 |
144 |
145 | def prettyprint(element)
146 |
147 |
148 |
prints the element to the commandline
149 |
Parameters
150 |
element (Element): element to print
151 |
152 |
153 |
154 | Expand source code
155 |
156 |
def prettyprint(element):
157 | """ prints the element to the commandline
158 |
159 | Parameters
160 | ----------
161 | element (Element): element to print
162 |
163 | """
164 | rough = ET.tostring(element,'utf-8')
165 | reparsed = mini.parseString(rough)
166 | print(reparsed.toprettyxml(indent="\t"))
This is a collection of ready to use functions, to generate standard road snipets, like:
54 | - Simple straight road
55 | - Spiral-Arc-Spiral type of turns
56 | - …
import xml.etree.ElementTree as ET
30 |
31 |
32 |
33 |
34 | class Signal():
35 | """ the Signal describes a signal along a road
36 |
37 | Parameters
38 | ----------
39 | s (float): the start s value (along road) of the Signal
40 |
41 | x (float): start x coordinate of the Signal
42 |
43 | zoffset (float): height of the signal
44 |
45 | name (str): name of the signal
46 |
47 | country (int): country code
48 |
49 | type (str): type of signal
50 |
51 | subtype (str): subtype of signal
52 |
53 |
54 |
55 |
56 |
57 | Attributes
58 | ----------
59 | s (float): the start s value (along road) of the Signal
60 |
61 | x (float): start x coordinate of the Signal
62 |
63 | id (str): id of the signal
64 |
65 | name (str): name of the signal
66 | Methods
67 | -------
68 | get_element()
69 | Returns the full ElementTree of the class
70 |
71 | get_attributes()
72 | Returns a dictionary of all attributes of the class
73 | """
74 |
75 | def __init__(self,s,x,y,heading,geom_type):
76 | """ initalizes the Signal
77 |
78 | Parameters
79 | ----------
80 | s (float): the start s value (along road) of the geometry
81 |
82 | x (float): start x coordinate of the geometry
83 |
84 | y (float): start y coordinate of the geometry
85 |
86 | heading (float): heading of the geometry
87 |
88 | geom_type (Line, Spiral,ParamPoly3, or Arc): the type of geometry
89 |
90 | """
91 | self.s = s
92 | self.x = x
93 | self.y = y
94 |
95 |
96 | self.heading = heading
97 | self.geom_type = geom_type
98 | _,_,_,self.length = self.geom_type.get_end_data(self.x,self.y,self.heading)
99 |
100 | def get_end_data(self):
101 | return self.geom_type.get_end_data(self.x,self.y,self.heading)
102 |
103 | def get_start_data(self):
104 | x,y,heading,self.length = self.geom_type.get_start_data(self.x,self.y,self.heading)
105 | self.x = x
106 | self.y = y
107 | self.heading = heading + np.pi
108 | self.s = None
109 | return x,y,heading,self.length
110 |
111 | def set_s(self,s):
112 | self.s = s
113 |
114 | def get_attributes(self):
115 | """ returns the attributes of the _Geometry as a dict
116 |
117 | """
118 | retdict = {}
119 | retdict['s'] = str(self.s)
120 | retdict['x'] = str(self.x)
121 | retdict['y'] = str(self.y)
122 | retdict['hdg'] = str(self.heading)
123 | retdict['length'] = str(self.length)
124 | return retdict
125 |
126 |
127 | def get_element(self):
128 | """ returns the elementTree of the _Geometry
129 |
130 | """
131 | element = ET.Element('geometry',attrib=self.get_attributes())
132 | element.append(self.geom_type.get_element())
133 | return element
146 | class Signal
147 | (s, x, y, heading, geom_type)
148 |
149 |
150 |
the Signal describes a signal along a road
151 |
Parameters
152 |
s (float): the start s value (along road) of the Signal
153 |
154 | x (float): start x coordinate of the Signal
155 |
156 | zoffset (float): height of the signal
157 |
158 | name (str): name of the signal
159 |
160 | country (int): country code
161 |
162 | type (str): type of signal
163 |
164 | subtype (str): subtype of signal
165 |
166 |
Attributes
167 |
s (float): the start s value (along road) of the Signal
168 |
169 | x (float): start x coordinate of the Signal
170 |
171 | id (str): id of the signal
172 |
173 | name (str): name of the signal
174 |
175 |
Methods
176 |
get_element()
177 | Returns the full ElementTree of the class
178 |
179 | get_attributes()
180 | Returns a dictionary of all attributes of the class
181 |
182 |
initalizes the Signal
183 |
Parameters
184 |
s (float): the start s value (along road) of the geometry
185 |
186 | x (float): start x coordinate of the geometry
187 |
188 | y (float): start y coordinate of the geometry
189 |
190 | heading (float): heading of the geometry
191 |
192 | geom_type (Line, Spiral,ParamPoly3, or Arc): the type of geometry
193 |
194 |
195 |
196 | Expand source code
197 |
198 |
class Signal():
199 | """ the Signal describes a signal along a road
200 |
201 | Parameters
202 | ----------
203 | s (float): the start s value (along road) of the Signal
204 |
205 | x (float): start x coordinate of the Signal
206 |
207 | zoffset (float): height of the signal
208 |
209 | name (str): name of the signal
210 |
211 | country (int): country code
212 |
213 | type (str): type of signal
214 |
215 | subtype (str): subtype of signal
216 |
217 |
218 |
219 |
220 |
221 | Attributes
222 | ----------
223 | s (float): the start s value (along road) of the Signal
224 |
225 | x (float): start x coordinate of the Signal
226 |
227 | id (str): id of the signal
228 |
229 | name (str): name of the signal
230 | Methods
231 | -------
232 | get_element()
233 | Returns the full ElementTree of the class
234 |
235 | get_attributes()
236 | Returns a dictionary of all attributes of the class
237 | """
238 |
239 | def __init__(self,s,x,y,heading,geom_type):
240 | """ initalizes the Signal
241 |
242 | Parameters
243 | ----------
244 | s (float): the start s value (along road) of the geometry
245 |
246 | x (float): start x coordinate of the geometry
247 |
248 | y (float): start y coordinate of the geometry
249 |
250 | heading (float): heading of the geometry
251 |
252 | geom_type (Line, Spiral,ParamPoly3, or Arc): the type of geometry
253 |
254 | """
255 | self.s = s
256 | self.x = x
257 | self.y = y
258 |
259 |
260 | self.heading = heading
261 | self.geom_type = geom_type
262 | _,_,_,self.length = self.geom_type.get_end_data(self.x,self.y,self.heading)
263 |
264 | def get_end_data(self):
265 | return self.geom_type.get_end_data(self.x,self.y,self.heading)
266 |
267 | def get_start_data(self):
268 | x,y,heading,self.length = self.geom_type.get_start_data(self.x,self.y,self.heading)
269 | self.x = x
270 | self.y = y
271 | self.heading = heading + np.pi
272 | self.s = None
273 | return x,y,heading,self.length
274 |
275 | def set_s(self,s):
276 | self.s = s
277 |
278 | def get_attributes(self):
279 | """ returns the attributes of the _Geometry as a dict
280 |
281 | """
282 | retdict = {}
283 | retdict['s'] = str(self.s)
284 | retdict['x'] = str(self.x)
285 | retdict['y'] = str(self.y)
286 | retdict['hdg'] = str(self.heading)
287 | retdict['length'] = str(self.length)
288 | return retdict
289 |
290 |
291 | def get_element(self):
292 | """ returns the elementTree of the _Geometry
293 |
294 | """
295 | element = ET.Element('geometry',attrib=self.get_attributes())
296 | element.append(self.geom_type.get_element())
297 | return element