pyoscx / scenariogeneration

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

How to lane link two roads where the number of lanes is not the same #83

Closed johschmitz closed 2 years ago

johschmitz commented 2 years ago

In order to create a highway exit lane I am thinking about using a road to road link instead of a new lane section in order to simplify my life for the moment. However, as far as I know the scenariogeneration lib only allow linking roads with the same number of lanes at the moment. Would it be possible to provide an additional create_lane_links() method which takes two lists with the lane numbers to be linked with each other as additional inputs? Or maybe it could even check which lanes have zero width and skip them during the linking but that would probably be too much magic already. The API with the two lists shouldn't be too difficult though I guess?

MandolinMicke commented 2 years ago

Hmm, are you using create_lane_links directly for all your roads? will junctions be involved?

johschmitz commented 2 years ago

Currently, I am using create_lane_links directly on all roads. For this new use-case I am currently not interested in junctions, just direct normal road to road connections. Don't see though why it couldn't work for junctions as well. I imagine something like this: create_lane_links_uneven(road_a, road_b, [2,1,-1,-2,-3],[2,1,-1,-2,-4]) Then you link lane -2 to -2 and -3 to -4 and lane -3 of road_b is not linked. Does that make sense? Or do you maybe even have a better idea?

johschmitz commented 2 years ago

Note: could also call it _unequal instead of _uneven.

MandolinMicke commented 2 years ago

Why I ask about junctions is that the incoming road does not link with junction lanes (that is what the junction element is for), so there is quite a difference (that part is usually taken care of in _createjunction).

But as you said just a function to link with a fixed list shouldn't be that hard. Under the assumption that the input will not be checked if it is correct or not, but up to the user to make sure the lists are what they want (so if the link between the roads are "successor-successor" it will excpect the user to take that into account)

johschmitz commented 2 years ago

Ah I see your question now. I have an extra path in my code to apply the create_lane_links for the incoming roads. Regarding the input check it would be good if an error could be thrown for some simple problems. Especially if one of the lanes does not exist at all. Or if the length of the two lists is not identical.

MandolinMicke commented 2 years ago

I think this would be a nice addition, I'm not completely sure how to solve for junctions though...

johschmitz commented 2 years ago

I don't see the junction problem? Maybe it is a misunderstanding. I go kind of manually, find the incoming and the connecting road and then lane link them. So I guess you have to do absolutely nothing regarding junctions for this issue?

johschmitz commented 2 years ago

Maybe you mean that one of the inputs of the method can be a junction? Could this case maybe just be excluded for now?

MandolinMicke commented 2 years ago

right now the create_lane_links takes care of if the road is a connecting road or a "normal" road.. So it would be nice to have it. But as a first attempt that can be thrown as an error

johschmitz commented 2 years ago

I guess something like create_lane_links_unequal(incoming_road_a, connecting_road_b, [2,1,-1,-2,-3],[2,1,-1,-2,-4]) should work? Or is there something I am missing? But something like create_lane_links_unequal(road_a, junction_x, [2,1,-1,-2,-3],[2,1,-1,-2,-4]) would be problematic. If you really go down this path giving it a new name with _unequal postfix instead of some optional arguments to create_lane_links() itself, then the documentation can explain for each of the two methods what are possible inputs.

MandolinMicke commented 2 years ago

b20a6516577b9b178f736377059dafa90506f111 There is a trail implementation, check if it works as you expect.

johschmitz commented 2 years ago

Okay cool, perfect thanks. Hope it is fine to keep the ticket open for some time until I get there to confirm. I think there is a typo in there: land vs lane

MandolinMicke commented 2 years ago

yeah, we'll keep it open until you have tried it out..

johschmitz commented 2 years ago

I am trying this out now. First thing I noticed is that it should rather be called create_lane_links_by_ids instead of create_lane_links_unequal since they do not necessarily need to be "unequal" and I am now trying to use it for all links, unequal and equal ones.

Now when I run it I am getting this error:

in create_lane_links_unequal
    road1.lanes.lanesections[first_connecting_lanesec].leftlanes[road1_land_ids[i]].add_link(first_linktype,road2_land_ids[i])
IndexError: list index out of range

Even for 2 roads with just one left lane and one right lane and the lane ID list looking like [-1,0,1]. Will try to create a minimal example now to see where the problem lies.

johschmitz commented 2 years ago

Here is the promised example:

""" Example for linking roads with unequal number of lanes.
"""

from scenariogeneration import xodr
import os

# Create roads
length_road = 100.0
road_first = xodr.create_road([xodr.Line(length_road)], 1, 2, 3)
road_second = xodr.create_road([xodr.Line(length_road)], 2, 2, 4)
# Make a new lane open up/branch out
new_lane_width = 3.0
road_second.lanes.lanesections[0].rightlanes[2].a = 0.0
road_second.lanes.lanesections[0].rightlanes[2].b = 0.0
road_second.lanes.lanesections[0].rightlanes[2].c = 3.0/length_road**2 * new_lane_width
road_second.lanes.lanesections[0].rightlanes[2].d = -2.0/length_road**3 * new_lane_width

## Create the OpenDrive class (Master class)
odr = xodr.OpenDrive('myroads')

## Finally add roads to Opendrive
odr.add_road(road_first)
odr.add_road(road_second)

road_first.add_successor(xodr.ElementType.road, 2, xodr.ContactPoint.start)
road_second.add_predecessor(xodr.ElementType.road, 1, xodr.ContactPoint.end)

# Do not link the new lane
link_lane_ids_first = [2,1,0,-1,-2,-3]
link_lane_ids_second = [2,1,0,-1,-2,-4]

xodr.create_lane_links_unequal(road_first, road_second, link_lane_ids_first, link_lane_ids_second)

# Adjust initial positions of the roads looking at succ-pred logic
odr.adjust_startpoints()

# write the OpenDRIVE file as xodr using current script name
odr.write_xml(os.path.basename(__file__).replace('.py', '.xodr'))
mander76 commented 2 years ago

Well, one thing that might cause issues is that you should not use the 0 lane? that I don't think it will fix..

johschmitz commented 2 years ago

Could you add an error message if lane ID 0 is in one of the lists?

mander76 commented 2 years ago

Done

johschmitz commented 2 years ago

In which branch is the update? Can't get the example from above working even if I remove the 0s from the lane id lists. Should be like this, right:

link_lane_ids_first = [2,1,-1,-2,-3]
link_lane_ids_second = [2,1,-1,-2,-4]
mander76 commented 2 years ago

master

johschmitz commented 2 years ago

This seems to be working fine now. The only thing which could be improved would be additional checks if someone supplies invalid lane IDs. Is there an easy way to check this already implemented? Other than that I think this can be closed.