File size: 4,424 Bytes
1811aab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
"""Background traffic and the scene description saved for the coarse proxy."""
from __future__ import annotations

import math
from dataclasses import dataclass, field

import carla

# level bounding boxes exported for the coarse proxy: CARLA label -> CWM class
STATIC_LABELS = {"Buildings": 0, "Walls": 0, "Fences": 0, "Poles": 0, "TrafficLight": 0, "TrafficSigns": 0,
                 "Static": 0, "Dynamic": 0, "Bridge": 0, "GuardRail": 0, "Vegetation": 5, "Water": 2}
SCENE_RADIUS_M = 300.0


@dataclass
class Traffic:
    actors: list = field(default_factory=list)
    controllers: list = field(default_factory=list)
    vehicles: list = field(default_factory=list)
    walkers: list = field(default_factory=list)


def spawn_traffic(world, bp, rng, n_vehicles: int, n_walkers: int) -> Traffic:
    """Parked vehicles (physics off: no traffic manager, it segfaults libcarla on some nodes, and a
    static street is what a revisit dataset wants) and AI-driven background pedestrians."""
    t = Traffic()
    spawns = world.get_map().get_spawn_points()
    rng.shuffle(spawns)
    vbps = [b for b in bp.filter("vehicle.*") if int(b.get_attribute("number_of_wheels")) == 4]
    for sp in spawns[:n_vehicles]:
        v = world.try_spawn_actor(rng.choice(vbps), sp)
        if v:
            v.set_simulate_physics(False)
            t.actors.append(v)
            t.vehicles.append(v)
    wbps = bp.filter("walker.pedestrian.*")
    ctrl_bp = bp.find("controller.ai.walker")
    for _ in range(n_walkers):
        loc = world.get_random_location_from_navigation()
        if loc is None:
            continue
        w = world.try_spawn_actor(rng.choice(wbps), carla.Transform(loc + carla.Location(z=1.0)))
        if w:
            t.actors.append(w)
            t.walkers.append(w)
            t.controllers.append(world.spawn_actor(ctrl_bp, carla.Transform(), w))
    world.tick()
    for c in t.controllers:
        c.start()
        c.go_to_location(world.get_random_location_from_navigation())
        c.set_max_speed(1.0 + rng.random() * 0.6)
    return t


def adult_walkers(bp):
    return [b for b in bp.filter("walker.pedestrian.*")
            if not (b.has_attribute("age") and b.get_attribute("age").as_str() == "child")]


def frame_record(hero, walkers) -> dict:
    """Per-frame scene state for the coarse proxy: protagonist bones, background walker poses."""
    bones = {bt.name: [round(bt.world.location.x, 3), round(bt.world.location.y, 3), round(bt.world.location.z, 3)]
             for bt in hero.get_bones().bone_transforms}
    others = []
    for w in walkers:
        wt = w.get_transform()
        others.append([round(wt.location.x, 2), round(wt.location.y, 2), round(wt.location.z, 2), round(wt.rotation.yaw, 1)])
    return dict(bones=bones, walkers=others)


def scene_static(world, centre, hidden, vehicles) -> dict:
    """Level boxes, driving-lane waypoints and parked vehicles within SCENE_RADIUS_M of `centre`.
    Objects switched off for the walk (`hidden`: their box centres) are left out."""
    L = carla.CityObjectLabel
    cx, cy = centre
    boxes = []
    for name, cls in STATIC_LABELS.items():
        if not hasattr(L, name):
            continue
        for bb in world.get_level_bbs(getattr(L, name)):
            if math.hypot(bb.location.x - cx, bb.location.y - cy) > SCENE_RADIUS_M:
                continue
            if any(abs(bb.location.x - h[0]) < 0.05 and abs(bb.location.y - h[1]) < 0.05
                   and abs(bb.location.z - h[2]) < 0.05 for h in hidden):
                continue
            boxes.append(dict(cls=cls, label=name, c=[bb.location.x, bb.location.y, bb.location.z],
                              e=[bb.extent.x, bb.extent.y, bb.extent.z],
                              r=[bb.rotation.pitch, bb.rotation.yaw, bb.rotation.roll]))
    lanes = []
    for w in world.get_map().generate_waypoints(2.0):
        p = w.transform.location
        if math.hypot(p.x - cx, p.y - cy) <= SCENE_RADIUS_M:
            lanes.append([p.x, p.y, p.z, w.transform.rotation.yaw, w.lane_width])
    vboxes = []
    for v in vehicles:
        bb, vt = v.bounding_box, v.get_transform()
        c = vt.transform(bb.location)
        vboxes.append(dict(c=[c.x, c.y, c.z], e=[bb.extent.x, bb.extent.y, bb.extent.z],
                           r=[vt.rotation.pitch, vt.rotation.yaw, vt.rotation.roll]))
    return dict(boxes=boxes, lanes=lanes, vehicles=vboxes)