pyoscx / scenariogeneration

Python library to generate linked OpenDRIVE and OpenSCENARIO files
Mozilla Public License 2.0
255 stars 81 forks source link

Contact point missmatch with road(s) connected to common junction on both ends #145

Open johschmitz opened 1 year ago

johschmitz commented 1 year ago

I am trying to find an issue with the create_junction() method when I create a "8" track with two arc roads directly connected to a four way junction at both of their ends.

Link to the method: https://github.com/pyoscx/scenariogeneration/blob/d9911c161904d2a24ecb035e173ade2376efabb7/scenariogeneration/xodr/generators.py#L976

It seems that in this case the contact points are not set correctly.

I thought that maybe inside the method I would have to replace

conne1 = Connection(jr.successor.element_id, jr.id, ContactPoint.end)

with

conne1 = Connection(jr.successor.element_id, jr.id, jr.successor.contact_point)

in order to fix it but it still does not seem to work completely. Maybe there is also a related bug in esmini or maybe I am just doing something wrong on my end. I can sit and work out a minimal example if needed to solve this or maybe you see it immediately. Just let me know.

MandolinMicke commented 1 year ago

That function is slightly outdated, but there to keep backwards compability. But that function is very sensitive that all predecessors and successors are set properly, the only tip I can give is that.

Have you tried using the new JunctionCreator class instead, it's more generic and can handle much more

johschmitz commented 1 year ago

I guess I will then have a look if the new API can now work for my use case and/or build a minimal example to understand exactly what is going wrong. I think the problem was that no custom connecting roads were supported and then I had to write some of the low level code myself and used this old method so that I did at least not have to write everything on my own.

MandolinMicke commented 1 year ago

Ah, but did you try out the change I made in a branch https://github.com/pyoscx/scenariogeneration/issues/127#issuecomment-1316574691?

johschmitz commented 1 year ago

So far I did not find time to try this to be honest, since the other approach was working and there was a lot of changes and bugfixes I needed to do first. Just came back to this point this week. I think this bug that I have now is a good reason though to revisit this topic.

johschmitz commented 1 year ago

@MandolinMicke I am playing with the common junction generator now and I noticed one thing which is a little bit confusing. There is a method called add_connection() which actually creates an OpenDRIVE connecting road. A "connection" is defined slightliy differently in the OpenDRIVE standard. See "t_junction_connection" in the UML Model (https://opendrive-uml.web.app/index.html?goto=2:54 or Chapter 10.2. Incoming roads in OpenDRIVE 1.7). You might want to overthink this name. Maybe call it create_connecting_road() and deprecate the add_connection() and remove it after some time or so.

johschmitz commented 1 year ago

I am trying to build the 8 course with two roads and one junction but it does not quite work:

import os
from scenariogeneration import xodr
from math import pi

# Initalize the junction creator
junction_id = 100
junction_creator = xodr.DirectJunctionCreator(id=junction_id, name="my direct junction")

# Create 2 roads, and add the successor/predecessor junction

road1 = xodr.create_road(xodr.Arc(curvature=0.1, angle=3/2*pi), id=1, left_lanes=1, right_lanes=1)
road2 = xodr.create_road(xodr.Arc(curvature=0.1, angle=3/2*pi), id=2, left_lanes=1, right_lanes=1)

# Create direct junction connection to all common lanes between the main roads

junction_creator = xodr.CommonJunctionCreator(id=100, name="my_junction")

junction_creator.add_incoming_road_cartesian_geometry(
    road1, x=0, y=0, heading=0, road_connection="predecessor"
)

junction_creator.add_incoming_road_cartesian_geometry(
    road1, x=10, y=10, heading=pi/2, road_connection="successor"
)

junction_creator.add_incoming_road_cartesian_geometry(
    road2, x=20, y=0, heading=pi, road_connection="predecessor"
)

junction_creator.add_incoming_road_cartesian_geometry(
    road2, x=10, y=-10, heading=-pi/2, road_connection="successor"
)

# Create the opendrive
odr = xodr.OpenDrive("my_road")

# Add the roads
junction_creator.add_connection(
    road_one_id=1, road_two_id=2, lane_one_id=1, lane_two_id=1
)
junction_creator.add_connection(
    road_one_id=2, road_two_id=1, lane_one_id=-1, lane_two_id=1
)

odr.add_road(road1)
odr.add_road(road2)

# Add the junction creator
odr.add_junction_creator(junction_creator)

# Adjust the roads and lanes
odr.adjust_roads_and_lanes()

# Write the OpenDRIVE file as xodr using current script name
odr.write_xml(os.path.basename(__file__).replace(".py", ".xodr"))

Any idea how to do this? Or should this not be allowed?

Probably I have to try with your branch next but I am not sure if this solves the problem. I guess there needs to be an additional argument to specify which end of the road to connect to.

johschmitz commented 1 year ago

One additional comment: I could maybe just disallow/prevent this case in my tool to work around this problem and I would be okay with that but it would be nicer if it would work.

mander76 commented 1 year ago

so you are trying to create an 8 shaped road? Haven't tried this before.. But my spontaneous thought is that scenariogeneration will not handle this at all... I can maybe see some real life applications for these, but for sure they are not supported now

MandolinMicke commented 7 months ago

This one was solved in the end right? @johschmitz

johschmitz commented 6 months ago

Hm I need to check later. I am not sure if this one was solved or a similar one. Do you have some kind of unit test though with only one junction and a single road that connects to that junction on both ends?

mander76 commented 6 months ago

not unittest no, there are some of these I would like to add tests to..