BeamNG / BeamNGpy

Python API for BeamNG.tech
https://beamng.tech
MIT License
255 stars 45 forks source link

Road Height Control in BeamNGpy #26

Closed tariqsameed closed 5 years ago

tariqsameed commented 5 years ago

I am trying to create multiple layers of the road in BeamNGpy in the scenario. The asphalt road and lane marking lie on the same level (height). Hence, the lane marking is not visible in BeamNG scenario. The API should provide a method to control the road position vertically in GridMap.

alessiogambi commented 5 years ago

Maybe it would be enough to have a flag to enable or disable the lane marking and let the implementation of the API do the rendering?

tariqsameed commented 5 years ago

The API rendering does not support the overlaying of roads. The sample output of asphalt road with white lane marking is attached.

image

Without asphalt road, I can see the lane marking in BeamNG scenario.

image

To visualize the lane marking in BeamNG, I need to place the lane marking just above the road. For this, the API should provide the placement of Z coordinate in BeamNG road creation.

alessiogambi commented 5 years ago

Correct, the Z value let users to force the rendering order of roads and marking. However, the question here is different: Would it be better to have the users play around with Z values while creating roads (fine control, more complex), or would it be better to add a flag to the API that simply turns on a default lane marking (less control, less complexity)?

tariqsameed commented 5 years ago

Would it be better to have the users play around with Z values while creating roads (fine control, more complex), I believe that users should play around the Z values while creating the road because of the elevation control of the roads etc. The lane marking is completely dynamic depend upon the width and number of lanes in the road segment.

Would it be better to add a flag to the API that simply turns on a default lane marking (less control, less complexity)? The default flag will not help us to handle the lane markings at the intersections etc. The default behavior might generate a different number of lanes for a given road's width and lanes.

TriHuynh00 commented 5 years ago

If our goal is to place lane marking(s) on top of a road segment (both lane markings and road segments are DecalRoad objects), then you can modify the renderPriority property to make the lane marking visible on top of the road.

The lower the renderPriority value, the higher the rendering layer of the object. For example, renderPriority = 1 means render this object on top of all objects, and renderPriority = 2 means it is placed below any object with renderPriority = 1, but above all objects with renderPriority > 2.

You can see the effect of renderPriority in the following image.

image

In this picture, yellow lane marking has renderPriority = 8, and the road segment has renderPriority = 10, so the yellow lane marking is placed on top of the road.

To open this property windows, press F11, on the top right corner, expand your scenario, until you find a prefab (a closed orange box icon) with your scenario name. Unpack it, and you will see all the objects in your scenario. Then find the properties you want to modify and update it.

tariqsameed commented 5 years ago

Well, you provided great information :). I didn't see any methods in BeamNGpy to set the render priority of the objects. I have set it programmatically during scenario creation.

TriHuynh00 commented 5 years ago

Thanks, it is nice to hear that the information is helpful to you :D

Maybe I should mention, BeamNG AI can navigate on a road segment, even if it is below another layer and not visible (an invisible texture is assigned to it). As long as you set the drivability param to 1.

alessiogambi commented 5 years ago

@tariqsameed Maybe you can close this issue then? Possibly you can open a new issue and provide a pull request to solve it?

Palculator commented 5 years ago

The prefab template uses the render_priority field of the road class: https://github.com/BeamNG/BeamNGpy/blob/master/src/beamngpy/templates/prefab#L42

So you should be able to specify render priority by passing render_priority=10 for example in the road constructor.

tariqsameed commented 5 years ago

The render_priority=10 is not set in the constructor of the Road. There is no variable defined in the Road constructor.

` Creates a new road instance using the given material name. The material name needs to match a material that is part of the level in the simulator this road will be placed in.

    Args:
        material (str): Name of the material this road uses. This affects
                        how the road looks visually and needs to match a
                        material that's part of the level this road is
                        placed in.
        rid (str): Optional string setting this road's name. If specified,
                   needs to be unique with respect to other roads in the
                   level/scenario.
        interpolat (bool): Whether to apply Catmull-Rom spline
                           interpolation to smooth transition between the
                           road's nodes.
    """
    self.material = material

    self.rid = rid

    self.drivability = options.get('drivability', 1)
    self.one_way = options.get('one_way', False)
    self.flip_direction = options.get('flip_direction', False)
    self.looped = options.get('looped', False)
    self.smoothness = options.get('smoothness', 0.5)
    self.break_angle = options.get('break_angle', 3)
    self.texture_length = options.get('texture_length')

    self.one_way = '1' if self.one_way else '0'
    self.flip_direction = '1' if self.flip_direction else '0'
    self.looped = '1' if self.looped else '0'

    if interpolate:
        self.improved_spline = '1'
    else:
        self.improved_spline = '0'
        self.break_angle = 359.9

    self.nodes = list()`
TriHuynh00 commented 5 years ago

Perhaps @Signaltonsalat means that after you construct a Road object, you can add a renderPriority property into the object. For example:

road1 = Road("invisible_texture", "", true)

// Add a custom property, like renderPriority road1.renderPriority = "10"

// Call the add road function to append this road1 // object with custom property inside the scenario beamngpy.add_road(road1)

tariqsameed commented 5 years ago

Perhaps @Signaltonsalat means that after you construct a Road object, you can add a renderPriority property into the object. For example:

road1 = Road("invisible_texture", "", true)

// Add a custom property, like renderPriority road1.renderPriority = "10"

// Call the add road function to append this road1 // object with custom property inside the scenario beamngpy.add_road(road1)

The renderPriority does not exist in road object.

TriHuynh00 commented 5 years ago

In python, a property does not have to be declared inside an object constructor so that it can be used. For example, the following code define a new property thirdProp, which is not declared in the constructor of the class Klasse.

class Klasse:
    def __init__(self):
        self.firstProp = "first"
        self.secProp = "sec"

    def printProp(self, klasse):
        try:
            print("{} {} {}".format(klasse.firstProp, klasse.secProp, klasse.thirdProp))
        except:
            print("thirdProp is not there")

a = Klasse()
a.thirdProp = "third"
a.printProp(a)

The output will be "first sec third"

If you remove a.thirdProp = "third" line, an exception will be thrown

Likewise, after you instantiate a Road object, you can define a new renderPriority property value before calling add_road() method. Afterward, beamngpy should write road.renderPriority property in the road template to construct the road.

tariqsameed commented 5 years ago

@SoftLegend I tried your method by

  1. passing the value into the constructor
  2. defining a renderPriority property before calling add_road() method.

Both methods do not provide any result. There might be another way of doing it. I am leaving the render priority work for now and may do it in the future on new releases.