Skip to content

Commit

Permalink
Crosswalk is available now. (#549)
Browse files Browse the repository at this point in the history
* add cross walk

* fix

* crosswalk available

* crosswalk render pipeline

* format

* update pipeline config
  • Loading branch information
QuanyiLi committed Nov 9, 2023
1 parent 0d43709 commit cc3ad2e
Show file tree
Hide file tree
Showing 14 changed files with 320 additions and 18 deletions.
24 changes: 24 additions & 0 deletions metadrive/component/map/base_map.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
from metadrive.utils.shapely_utils.geom import find_longest_parallel_edges, find_longest_edge
import geopandas as gpd
from shapely.ops import unary_union
from metadrive.utils.utils import time_me
Expand Down Expand Up @@ -210,6 +211,29 @@ def get_semantic_map(
] for p in line
]
cv2.polylines(mask, np.array([points]).astype(np.int32), False, color, polyline_thickness)

if "crosswalk" in layer:
for id, sidewalk in self.crosswalks.items():
polygon = sidewalk["polygon"]
points = [
[
int((x - center_p[0]) * pixels_per_meter + size / 2),
int((y - center_p[1]) * pixels_per_meter) + size / 2
] for x, y in polygon
]
# edges = find_longest_parallel_edges(polygon)
# p_1, p_2 = edges[0]
p_1, p_2 = find_longest_edge(polygon)[0]
dir = (
p_2[0] - p_1[0],
p_2[1] - p_1[1],
)
# 0-2pi
angle = np.arctan2(*dir) / np.pi * 180 + 180
# normalize to 0.4-0.714
angle = angle / 1000 + MapTerrainSemanticColor.get_color(MetaDriveType.CROSSWALK)
cv2.fillPoly(mask, np.array([points]).astype(np.int32), color=angle)

self._semantic_map = mask
return self._semantic_map

Expand Down
16 changes: 16 additions & 0 deletions metadrive/component/scenario_block/scenario_block.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import math
from metadrive.utils.shapely_utils.geom import cut_polygon_along_parallel_edges
from metadrive.constants import CollisionGroup
from metadrive.utils.utils import time_me
import numpy as np
Expand Down Expand Up @@ -166,6 +167,21 @@ def construct_sidewalk(self):
body_node.setIntoCollideMask(CollisionGroup.Sidewalk)
self._node_path_list.append(np)

def construct_crosswalk(self):
"""
Construct the crosswalk
"""
raise DeprecationWarning("The Crosswalk is built on terrain now")
if self.engine.global_config["show_crosswalk"] and not self.engine.use_render_pipeline:
for sidewalk in self.crosswalks.values():
polygon = sidewalk["polygon"]
np = make_polygon_model(polygon, 0.0)
np.reparentTo(self.sidewalk_node_path)
np.setPos(0, 0, -0.05)
np.setTexture(self.side_texture)
# np.setTexture(self.ts_normal, self.side_normal)
self._node_path_list.append(np)

@property
def block_network_type(self):
return EdgeRoadNetwork
Expand Down
5 changes: 5 additions & 0 deletions metadrive/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,11 @@ def get_color(type):
elif MetaDriveType.is_white_line(type) or MetaDriveType.is_road_boundary_line(type):
# return (0, 0, 0, 1)
return 0.3
elif type == MetaDriveType.CROSSWALK:
# The range of crosswalk value is 0.4 <= value < 0.76,
# so people can save the angle (degree) of the crosswalk in attribute map
# the value * 10 = angle of crosswalk. It is a trick for saving memory.
return 0.4 # this value can be overwritten latter
else:
raise ValueError("Unsupported type: {}".format(type))
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Expand Down
20 changes: 19 additions & 1 deletion metadrive/engine/core/terrain.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,14 @@ def reset(self, center_position):
if self.render:
# Make semantics for shader terrain
assert self.engine.current_map is not None, "Can not find current map"
layer = ["lane", "lane_line"]
if self.engine.global_config["show_crosswalk"]:
layer.append("crosswalk")
semantics = self.engine.current_map.get_semantic_map(
size=self._semantic_map_size,
pixels_per_meter=self._semantic_map_pixel_per_meter,
polyline_thickness=int(1024 / self._semantic_map_size),
layer=["lane", "lane_line"]
layer=layer
)
semantic_tex = Texture()
semantic_tex.setup2dTexture(*semantics.shape[:2], Texture.TFloat, Texture.F_red)
Expand Down Expand Up @@ -247,6 +250,9 @@ def _set_terrain_shader(self, engine, attribute_tex):
self._mesh_terrain.set_shader_input("road_normal", self.road_texture_normal)
self._mesh_terrain.set_shader_input("road_rough", self.road_texture_rough)
self._mesh_terrain.set_shader_input("elevation_texture_ratio", self._elevation_texture_ratio)

# crosswalk
self._mesh_terrain.set_shader_input("crosswalk_tex", self.crosswalk_tex)
self._terrain_shader_set = True
self._mesh_terrain.set_shader_input("attribute_tex", attribute_tex)

Expand Down Expand Up @@ -473,6 +479,18 @@ def _load_mesh_terrain_textures(self, engine, anisotropic_degree=16, filter_type
self.yellow_lane_line = Texture("white lane line")
self.yellow_lane_line.load(yellow_lane_line)

# crosswalk
tex = np.frombuffer(self.road_texture.getRamImage().getData(), dtype=np.uint8)
tex = tex.copy()
tex = tex.reshape((self.road_texture.getYSize(), self.road_texture.getXSize(), 3))
step_size = 64
for x in range(0, 2048, step_size * 2):
tex[x:x + step_size, ...] = 220
self.crosswalk_tex = Texture()
self.crosswalk_tex.setup2dTexture(*tex.shape[:2], Texture.TUnsignedByte, Texture.F_rgb)
self.crosswalk_tex.setRamImage(tex)
# self.crosswalk_tex.write("test_crosswalk.png")

def _make_random_terrain(self, texture_size, terrain_size, heightfield):
"""
Deprecated
Expand Down
2 changes: 2 additions & 0 deletions metadrive/envs/base_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@
use_mesh_terrain=False,
# use full-size mesh terrain
full_size_mesh=True,
# show crosswalk
show_crosswalk=False,

# ===== Others =====
# Force to generate objects in the left lane.
Expand Down
5 changes: 3 additions & 2 deletions metadrive/envs/real_data_envs/nuscenes_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@
"curriculum_level": 1,
"show_fps": True,
"show_sidewalk": True,
"show_crosswalk": True,
# "pstats": True,
# "use_mesh_terrain": True,
# "debug": True,
"no_static_vehicles": False,
# "pstats": True,
# "render_pipeline": True,
"render_pipeline": True,
"window_size": (1600, 900),
"camera_dist": 9,
"start_scenario_index": 0,
Expand All @@ -46,7 +47,7 @@
lane_line_detector=dict(num_lasers=0, distance=50),
side_detector=dict(num_lasers=12, distance=50)
),
"data_directory": AssetLoader.file_path("nuscenes"),
"data_directory": AssetLoader.file_path("nuscenes", return_raw_style=False),
# "drivable_area_extension": 0,
}
)
Expand Down
2 changes: 1 addition & 1 deletion metadrive/render_pipeline/config/plugins.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ overrides:
num_samples: 12

pssm:
max_distance: 512
max_distance: 128
logarithmic_factor: 2.37
sun_distance: 256
split_count: 4
Expand Down
13 changes: 11 additions & 2 deletions metadrive/shaders/terrain.frag.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ uniform sampler2D white_tex;
uniform sampler2D road_tex;
uniform sampler2D road_normal;
uniform sampler2D road_rough;
uniform sampler2D crosswalk_tex;

uniform sampler2D grass_tex;
uniform sampler2D grass_normal;
Expand Down Expand Up @@ -125,11 +126,19 @@ void main() {
if ((attri.r > 0.01) && terrain_uv.x>r_min && terrain_uv.y > r_min && terrain_uv.x<r_max && terrain_uv.y<r_max){
float value = attri.r; // Assuming it's a red channel texture
if (value < 0.11) {
// Semantics for value 1
// yellow
diffuse=texture(yellow_tex, terrain_uv * road_tex_ratio).rgb;
} else if (value < 0.21) {
// Semantics for value 2
// road
diffuse = texture(road_tex, terrain_uv * road_tex_ratio).rgb;
} else if (value < 0.31) {
// white
diffuse = texture(white_tex, terrain_uv * road_tex_ratio).rgb;
} else if (value > 0.3999 || value < 0.760001) {
// crosswalk
float theta=(value-0.39999) * 1000/180 * 3.1415926535;
vec2 new_terrain_uv = vec2(cos(theta)*terrain_uv.x - sin(theta)*terrain_uv.y, sin(theta)*terrain_uv.x+cos(theta)*terrain_uv.y);
diffuse = texture(crosswalk_tex, new_terrain_uv * road_tex_ratio).rgb;
} else{
// Semantics for value 4
diffuse = texture(white_tex, terrain_uv * road_tex_ratio).rgb;
Expand Down
13 changes: 11 additions & 2 deletions metadrive/shaders/terrain_effect.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ fragment:
uniform sampler2D yellow_tex;
uniform sampler2D white_tex;
uniform sampler2D road_tex;
uniform sampler2D crosswalk_tex;
uniform sampler2D road_normal;
uniform sampler2D road_rough;
Expand Down Expand Up @@ -121,10 +122,18 @@ fragment:
} else if (value < 0.21) {
// Semantics for value 2
diffuse = texture(road_tex, terrain_uv * road_tex_ratio).rgb;
} else{
} else if (value < 0.31) {
// Semantics for value 4
diffuse = texture(white_tex, terrain_uv * road_tex_ratio).rgb;
}
} else if (value > 0.3999 || value < 0.760001) {
// crosswalk
float theta=(value-0.39999) * 1000/180 * 3.1415926535;
vec2 new_terrain_uv = vec2(cos(theta)*terrain_uv.x - sin(theta)*terrain_uv.y, sin(theta)*terrain_uv.x+cos(theta)*terrain_uv.y);
diffuse = texture(crosswalk_tex, new_terrain_uv * road_tex_ratio).rgb;
} else {
// Others
diffuse = texture(white_tex, terrain_uv * road_tex_ratio).rgb;
}
m.shading_model = SHADING_MODEL_DEFAULT;
m.specular_ior = 1.51;
Expand Down
25 changes: 25 additions & 0 deletions metadrive/tests/test_component/texture_merge.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# import numpy
#
#
import numpy as np
from panda3d.core import Texture
import cv2
from metadrive.engine.asset_loader import AssetLoader
from metadrive.engine.engine_utils import initialize_engine
from metadrive.envs.base_env import BASE_DEFAULT_CONFIG

if __name__ == '__main__':
engine = initialize_engine(BASE_DEFAULT_CONFIG)
tex_origin = engine.loader.loadTexture(AssetLoader.file_path("textures", "asphalt", "diff_2k.png"))
tex = np.frombuffer(tex_origin.getRamImage().getData(), dtype=np.uint8)
tex = tex.copy()
tex = tex.reshape((tex_origin.getYSize(), tex_origin.getXSize(), 3))

for x in range(0, 2048, 512):
tex[x:x + 256, ...] = 220

cv2.imwrite("test_tex.png", tex)

# semantic_tex = Texture()
# semantic_tex.setup2dTexture(*semantics.shape[:2], Texture.TFloat, Texture.F_red)
# semantic_tex.setRamImage(semantics)
9 changes: 9 additions & 0 deletions metadrive/utils/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@


def get_np_random(seed=None, return_seed=False):
"""
Generating a numpy.RandomState give a seed
Args:
seed: seed for thr random number generator (rng)
return_seed: return the seed for seeding the rgg
Returns: rng (with seed)
"""
if seed is not None and not (isinstance(seed, int) and 0 <= seed):
raise logging.error('Seed must be a non-negative integer or omitted, not {}'.format(seed))

Expand Down
Empty file.

0 comments on commit cc3ad2e

Please sign in to comment.