HighwayEnv
HighwayEnv copied to clipboard
How the coordinate conversion mechanism work in this work?
Hi, thank for your excellent work!
I have a question about the coordinate conversion mechanism in this work.
For example, what does the s0
mean in road/graphics.py
. The corresponding code is as below:
`@classmethod
def display(cls, lane: AbstractLane, surface: WorldSurface) -> None:
"""
Display a lane on a surface.
:param lane: the lane to be displayed
:param surface: the pygame surface
"""
print(surface.get_height()) # surface.get_height() = screen.height
print(surface.get_width()) # surface.get_width() = screen.width
print(surface.origin)
stripes_count = int(2 * (surface.get_height() + surface.get_width()) / (cls.STRIPE_SPACING * surface.scaling))
s_origin, _ = lane.local_coordinates(surface.origin)
s0 = (int(s_origin) // cls.STRIPE_SPACING - stripes_count // 2) * cls.STRIPE_SPACING
print("s0 = {}".format(s0))
for side in range(2):
if lane.line_types[side] == LineType.STRIPED:
cls.striped_line(lane, surface, stripes_count, s0, side)
elif lane.line_types[side] == LineType.CONTINUOUS:
cls.continuous_curve(lane, surface, stripes_count, s0, side)
elif lane.line_types[side] == LineType.CONTINUOUS_LINE:
cls.continuous_line(lane, surface, stripes_count, s0, side)`
Could you give a detail document to introduce this.
Hi @Joe12138 , thanks!
Basically, a lane is described by a curve representing its centerline, and this curve is parameterized by its longitudinal abscissa. And any point which is not on the centerline also has a lateral coordinate, which is its (signed) distance to the centerline.
In your example, s_0 is the longitudinal coordinate (along the lane centerline) of the first stripe to be drawn.
For more references, see Frenet coordinate system, e.g. https://github.com/fjp/frenet#frenet-features
Thanks for your reply!
But I still cannot under the meaning of the source code.
For example,
- in the
class LaneGraphics
which is inroad/graphics.py
file, Does the parameterSTRIPE_SPACING
mean the distance between two stripes? - in method
display
, in theclass LaneGraphics
which is inroad/graphics.py
file, what does the parameterstripe_count
mean? (stripes_count = int(2 * (surface.get_height() + surface.get_width()) / (cls.STRIPE_SPACING * surface.scaling))
) Why do you use the perimeter of the screen to divide the pixel ofSTRIPE_SPACING
? Why does it meanstripe_count
? - in method 'continuous_line', in the
class LaneGraphics
which is inroad/graphics.py
file, is the calculation method of the parameter "ends" right? (ends = [longitudinal + stripes_count * cls.STRIPE_SPACING + cls.STRIPE_LENGTH]
) Does it need to be relative to the parameter of thelane.length
?
I am very sorry to bother you with these small question. But it is very important to help to construct an environment with .osm
file automatically.
Before answering your question, I want to stress that this code is used to render the lane graphics, so I don't think you need to understand this, it is not required for defining a road network and geometry. You simply need to be able to define lane segments in the world coordinates, and not worry about how this translates to pixel space for instance.
Here are my answers, however:
in the class LaneGraphics which is in road/graphics.py file, Does the parameter STRIPE_SPACING mean the distance between two stripes?
STRIPE SPACING is the distance between two starts of stripes, so the distance between two stripes + the stripe length
in method display, in the class LaneGraphics which is in road/graphics.py file, what does the parameter stripe_count mean? (stripes_count = int(2 * (surface.get_height() + surface.get_width()) / (cls.STRIPE_SPACING * surface.scaling))) Why do you use the perimeter of the screen to divide the pixel of STRIPE_SPACING? Why does it mean stripe_count? in method 'contin
This is just a simple heuristic, and there is probably a much better way of implementing this. Basically, the approach I had is to write a method that writes N stripes from a starting longitudinal position along the lane (defined in the lane's coordinate system), each stripe with a certain length and distance to the next stripe.
But to compute the longitudinal position of the first stripe, we need to be able to compute the intersections between the lane and the screen boundaries, which is not easy. As an approximate heuristic, I compute the longitudinal coordinate of the middle of the screen. Then, the distance from the center to the starting/ending longidutinal positions rendered on screen is upper-bounded by the screen diagonal, itself upper-bounded by the screen height+width. And since the road may not be straight, I add a *2 factor to make it more conservative. The number of stripes rendered in this road segment is thus the total distance (2 * (height + width)) divided by the stripe spacing. And since height+width is given in the pixel space (px) rather than world space (m), I need to scale if by the surface.scaling ratio.
in method 'continuous_line', in the class LaneGraphics which is in road/graphics.py file, is the calculation method of the parameter "ends" right? (ends = [longitudinal + stripes_count * cls.STRIPE_SPACING + cls.STRIPE_LENGTH]) Does it need to be relative to the parameter of the lane.length?
Yes, the longidutinal coordinate of the end of any stripe can be obtained by
- starting with the longitudinal position of the first stripe
- adding the spacing (distance + length, remember) of every stripe before
- adding the current stripe length
It is not related directly to the lane.length, since here we are looking at line segments rendered on screen, and the lane could be much longer and continue offscreen for an indefinite distance. So their is no direct relation between the two.
I hope that makes sense to you, I realize this is not the most intuitive, especially without a drawing. However, I do not think you have to bother with these. You should be able to simply define linear road segments by specifying their start and end world positions, and that should be enough.
Thanks for your patience reply!
I understood what you mean. Thank you very much again! Now, I have finished the work which I mentioned in #238. But it cannot fill the road correctly. Can you help me to address this problem? The problem is as below:
This is the road network shown in the INTERACTION dataset (You don't need to care the number.):
This is the road network constructed by this package.
Sorry! I don't know how to show the complete road network. Therefore, I only can show a part of the road network. As you can see, the road are not filled by the gray color. Can you help me to address this problem?
This is pretty weird, would you mind sharing the code that you used to generate this, so that I can have a look?
Sorry! I just saw your reply. Thank for your nice reply! I have fixed this bug. The reason is that the width of lanes in .osm
path is not always equal. So I have to change the road-drawing mechanism based on your code. This the results after fixing this bug:
The original Merge scene in .osm
file
The Merge scene in highway environment (just the initial result):
However, the
.osm
parser written by me cannot handle the .osm
file with different scenes. For example,
The original Roundabout scene in .osm
file
The Roundabout scene in highway environment (just the initial result):
For me, I really want to embed this function into highway-env. I am glad that I can complete this function with you. If you have free time and would like to do this with me, please let me know.
Anyway, thanks for your nice and patience reply!!!
Hi @Joe12138, this is very nice work! I also think this function would be very useful, and would be glad to help whenever I have some free time. Please feel free to share the source code of your current osm parser, and example scene that is not being correctly parsed or rendered, and I will have a look.
Thank you for your help!
The code of the osm
parser can be available at https://github.com/Joe12138/EnvBasedHDMap.git. I am sorry that these code are with less comments. The code of osm
parser are in osm_paerser
folder. The HD map files of the scenes are in the map
folder. Please let me know if your have any question about the code.
Thank you very much again!
Hi @Joe12138 I wanted to have a look today, but it seems that you are relying on the lanelet2 library, which requires quite heavy dependencies like ROS. I am a bit reluctant to install them, especially since I don't have any machine running on Linux at the moment, only Windows. Any change you may consider moving to lanelet2-parser instead, which is conveniently packaged with PyPi?
Also, I could not find any example script to run your project (e.g. which dataset_file_path
, osm_file_path
, vehicle_id
etc. should I use?)
Hi @eleurent ,
Thanks for your nice feedback!
I am sorry that I cannot do this (moving to lanelet2-parser) right now. Since I am writing my report and I will do it as soon as possible. But I can convert the information in .osm
file to .json
format just for your test.
Additionally, I have added an example script in my project.
All these have been done and more information about how to use can be found in the READEME.md
in the project.
Thank you for your nice help!
Again, please let me know if you have any question!
Hi @Joe12138 Many thanks for the json export, I managed to load the scenes you attached! (I noticed that you also use the Interaction Dataset to get the vehicle positions, but since I don't have this dataset and you need to fill a form to download it I simply commented out the vehicle loading part and put a dummy vehicle in the middle of the scene instead)
Here is what I got after loading the DR_USA_Roundabout_SR scene:
I first noticed that a few lane segments seem to have the points in their borders defined in the wrong order, which gives these 'diabolo' shapes:
To better see what's going on, I chose random colors for each Lane segment, and also drew red circles at each point of their border
By switching the order in which the right border of each lane is traversed, we can see that it fixes the three diabolo patches at the bottom, but not the one at the top:
So I guess there is something wrong in the order in which the point list of the two lane borders are generated from the osm.
Note that overlapping both conventions (left + reversed(right) as expected, and left + right in addition for faulty patches) would not work since it would draw inside regions outside of the polygon for non-convex lanes.
Another issue is that some points should be shared between the borders of two Lanes, but instead belong to only one of them. See e.g. the circled point at the bottom, which only belongs to the yellow patch while it should also belong to the purple patch below so that the dashed region is filled.
Finally, only looking at the lane borders and hiding the patches, it seems quite clear that the curved part of the roundabout has been traversed in the wrong order: see my annotation below (could be the reversed order)
where it should instead be something like this:
So all these issues seem to stem from how you read lanes in an OSM file, and convert them to Lane objects, and not to the rendering code itself. I'm not sure what else I could do to help, but I advise you to go back to your conversion code with these kind of visualization and try to ensure that everything is handled in the correct order.
Good luck! :)