Example #1
0
 def se2_from_curpos(self, cur_pos, cur_angle):
     """ Conversion from Duckietown Gym Simulator coordinates z"""
     H = self.children["tilemap"].H
     gx, gy, gz = cur_pos
     p = [gx, (H - 1) * self.tile_size - gz]
     transform = SE2Transform(p, cur_angle)
     return transform
Example #2
0
def create_lane_highlight(poses_sequence: SampledSequence, dw):
    def mapi(v):
        if isinstance(v, SE2Transform):
            return v.as_SE2()
        else:
            return v

    poses_sequence = poses_sequence.transform_values(mapi, np.ndarray)

    lane_pose_results = poses_sequence.transform_values(
        GetClosestLane(dw), object)

    visualization = PlacedObject()
    dw.set_object("visualization",
                  visualization,
                  ground_truth=SE2Transform.identity())
    for i, (timestamp, name2pose) in enumerate(lane_pose_results):
        for name, lane_pose_result in name2pose.items():
            assert isinstance(lane_pose_result, GetLanePoseResult)
            lane_segment = lane_pose_result.lane_segment
            rt = lane_pose_result.lane_segment_transform
            s = SampledSequence[Transform]([timestamp], [rt])
            visualization.set_object("ls%s-%s-lane" % (i, name),
                                     lane_segment,
                                     ground_truth=s)
            p = SampledSequence[Transform]([timestamp],
                                           [lane_pose_result.center_point])
            visualization.set_object("ls%s-%s-anchor" % (i, name),
                                     Anchor(),
                                     ground_truth=p)

    return lane_pose_results
Example #3
0
def get_tile_slots():
    LM = 0.5  # half tile
    # tile_offset
    to = 0.20
    # tile_curb
    tc = 0.05

    positions = {
        0: (+to, +tc),
        1: (+tc, +to),
        2: (-tc, +to),
        3: (-to, +tc),
        4: (-to, -tc),
        5: (-tc, -to),
        6: (+tc, -to),
        7: (+to, -tc),
    }

    po = PlacedObject()
    for i, (x, y) in positions.items():
        name = str(i)
        # if name in self.children:
        #     continue

        sl = SignSlot()
        # theta = np.deg2rad(theta_deg)
        theta = 0
        t = SE2Transform((-LM + x, -LM + y), theta)
        # noinspection PyTypeChecker
        po.set_object(name, sl, ground_truth=t)
    return po
def m1():
    outdir = get_comptests_output_dir()
    gm = load_map("udem1")

    # dw = DuckietownWorld()
    # for map_name, tm in gym_maps.items():
    #     DW.root.set_object(map_name, tm)

    root = PlacedObject()

    world = PlacedObject()
    root.set_object("world", world)
    origin = SE2Transform([1, 10], np.deg2rad(10))
    world.set_object("tile_map",
                     gm,
                     ground_truth=Constant[SE2Transform](origin))

    # d = dw.as_json_dict()
    # print(json.dumps(d, indent=4))
    # print(yaml.safe_dump(d, default_flow_style=False))
    #

    G = get_meausurements_graph(root)
    fn = os.path.join(outdir, "out1.pdf")
    plot_measurement_graph(root, G, fn)
    def se2_from_curpos(self, cur_pos, cur_angle):
        """ Conversion from Duckietown Gym Simulator coordinates z"""
        from duckietown_world import TileMap

        tilemap: TileMap = cast(TileMap, self.children["tilemap"])
        H = tilemap.H
        gx, gy, gz = cur_pos
        p = [gx, (H - 1) * self.tile_size - gz]
        transform = SE2Transform(p, cur_angle)
        return transform
Example #6
0
    def SE2Transform_from_lane_pose(self, lane_pose):
        beta = self.beta_from_along_lane(lane_pose.along_lane)
        # logger.info('beta: %s' % beta)
        center_point = self.center_point(beta)
        delta = np.array([0, lane_pose.lateral])

        rel = geo.SE2_from_translation_angle(delta, lane_pose.relative_heading)
        # logger.info('rel: %s' % geo.SE2.friendly(rel))
        res = geo.SE2.multiply(center_point, rel)

        return SE2Transform.from_SE2(res)
def get_transform(desc, tm, tile_size):
    rotate_deg = desc.get('rotate', 0)
    rotate = np.deg2rad(rotate_deg)

    if 'pos' in desc:
        pos = desc['pos']
        x = float(pos[0]) * tile_size
        # account for non-righthanded
        y = float(tm.W - pos[1]) * tile_size
        # account for non-righthanded
        rotate = -rotate
        transform = SE2Transform([x, y], rotate)
        return transform

    else:

        if 'pose' in desc:
            pose = Serializable.from_json_dict(desc['pose'])
        else:
            pose = SE2Transform.identity()

        if 'attach' in desc:
            attach = desc['attach']
            tile_coords = tuple(attach['tile'])
            slot = str(attach['slot'])

            x, y = get_xy_slot(slot)
            i, j = tile_coords

            u, v = (x + i) * tile_size, (y + j) * tile_size
            transform = SE2Transform([u, v], rotate)

            q = geo.SE2.multiply(transform.as_SE2(), pose.as_SE2())

            return SE2Transform.from_SE2(q)
        else:
            return pose
def wb1():
    outdir = get_comptests_output_dir()
    root = PlacedObject()
    tile_map = create_map(H=3, W=3)

    world = PlacedObject()
    root.set_object('world', world)

    placement = Constant[SE2Transform](SE2Transform.identity())

    world.set_object('map1', tile_map, ground_truth=placement)

    ego = PlacedObject()
    world_coordinates = Constant[SE2Transform](SE2Transform([0, 0], 0))

    world.set_object('ego', ego, ground_truth=world_coordinates)

    d = root.as_json_dict()
    # print(json.dumps(DW.root.as_json_dict(), indent=4))
    # print(yaml.safe_dump(d, default_flow_style=False))
    # print('------')
    r1 = Serializable.from_json_dict(d)
    # print('read: %s' % r1)
    d1 = r1.as_json_dict()
Example #9
0
    def __init__(self, kind, drivable, **kwargs):
        # noinspection PyArgumentList
        PlacedObject.__init__(self, **kwargs)
        self.kind = kind
        self.drivable = drivable

        self.fn_emissive = get_if_exists(self.style, kind, "emissive")
        self.fn_normal = get_if_exists(self.style, kind, "normals")
        self.fn = get_if_exists(self.style, kind, "texture")
        self.fn_metallic_roughness = get_if_exists(self.style, kind, "metallic_roughness")
        self.fn_occlusion = get_if_exists(self.style, kind, "occlusion")

        if not "slots" in self.children:
            slots = get_tile_slots()
            # noinspection PyTypeChecker
            self.set_object("slots", slots, ground_truth=SE2Transform.identity())
Example #10
0
    def __init__(self, kind, drivable, **kwargs):
        # noinspection PyArgumentList
        PlacedObject.__init__(self, **kwargs)
        self.kind = kind
        self.drivable = drivable

        from duckietown_world.world_duckietown.map_loading import get_texture_file

        try:
            self.fn = get_texture_file(kind)
        except KeyError as e:
            msg = f"Cannot find texture for tile of type {kind}"
            logger.warning(msg, e=e)

            self.fn = None
        # if kind in ['asphalt']:
        if not "slots" in self.children:
            slots = get_tile_slots()
            self.set_object("slots", slots, ground_truth=SE2Transform.identity())
Example #11
0
    def __init__(self, kind, drivable, **kwargs):
        PlacedObject.__init__(self, **kwargs)
        self.kind = kind
        self.drivable = drivable

        from duckietown_world.world_duckietown.map_loading import get_texture_file

        try:
            self.fn = get_texture_file(kind)
        except KeyError:
            msg = 'Cannot find texture for %s' % kind
            logger.warning(msg)

            self.fn = None
        # if kind in ['asphalt']:
        if not 'slots' in self.children:
            slots = get_tile_slots()
            self.set_object('slots',
                            slots,
                            ground_truth=SE2Transform.identity())
    def lane_pose(self, along_lane: float, lateral: float,
                  relative_heading: float) -> LanePose:
        beta = self.beta_from_along_lane(along_lane)
        center_point = self.center_point(beta)

        W2 = self.width / 2
        lateral_inside = -W2 <= lateral <= W2
        outside_right = lateral < -W2
        outside_left = W2 < lateral
        distance_from_left = np.abs(+W2 - lateral)
        distance_from_right = np.abs(-W2 - lateral)
        distance_from_center = np.abs(lateral)

        L = self.get_lane_length()
        along_inside = 0 <= along_lane < L
        along_before = along_lane < 0
        along_after = along_lane > L
        inside = lateral_inside and along_inside

        correct_direction = np.abs(relative_heading) <= np.pi / 2
        return LanePose(
            inside=inside,
            lateral_inside=lateral_inside,
            outside_left=outside_left,
            outside_right=outside_right,
            distance_from_left=distance_from_left,
            distance_from_right=distance_from_right,
            relative_heading=relative_heading,
            along_inside=along_inside,
            along_before=along_before,
            along_after=along_after,
            along_lane=along_lane,
            lateral=lateral,
            lateral_left=W2,
            lateral_right=-W2,
            distance_from_center=distance_from_center,
            center_point=SE2Transform.from_SE2(center_point),
            correct_direction=correct_direction,
        )
def get_skeleton_graph(po):
    """ Returns a graph with the lane segments of the map """

    # Get all the LaneSegments

    root = PlacedObject()

    class MeetingPoint(object):
        def __init__(self):
            self.point = None
            self.incoming = set()
            self.outcoming = set()

        def __repr__(self):
            return 'MP(%d %d | %s, %s)' % (len(
                self.incoming), len(
                    self.outcoming), self.incoming, self.outcoming)

    def discretize(tran):
        def D(x):
            return np.round(x, decimals=2)

        p, theta = geo.translation_angle_from_SE2(tran.as_SE2())
        return D(p[0]), D(p[1]), D(np.cos(theta)), D(np.sin(theta))

    meeting_points = defaultdict(MeetingPoint)

    for i, it in enumerate(iterate_by_class(po, LaneSegment)):
        lane_segment = it.object
        # lane_segment_fqn = it.fqn
        assert isinstance(lane_segment, LaneSegment), lane_segment
        absolute_pose = it.transform_sequence.asmatrix2d()

        lane_segment_transformed = transform_lane_segment(
            lane_segment, absolute_pose)

        identity = SE2Transform.identity()
        name = 'ls%03d' % i
        root.set_object(name, lane_segment_transformed, ground_truth=identity)

        p0 = discretize(lane_segment_transformed.control_points[0])
        p1 = discretize(lane_segment_transformed.control_points[-1])

        meeting_points[p0].point = lane_segment_transformed.control_points[0]
        meeting_points[p0].outcoming.add(name)
        meeting_points[p1].point = lane_segment_transformed.control_points[-1]
        meeting_points[p1].incoming.add(name)

    for k, mp in meeting_points.items():
        if (len(mp.incoming) == 0) or (len(mp.outcoming) == 0):
            msg = 'Completeness assumption violated at point %s: %s' % (k, mp)
            raise Exception(msg)

    # compress the lanes which are contiguous

    aliases = {}

    created = {}

    def resolve_alias(x):
        return x if x not in aliases else resolve_alias(aliases[x])

    for k, mp in list(meeting_points.items()):
        # continue
        if not (len(mp.incoming) == 1 and len(mp.outcoming) == 1):
            continue

        # not necessary anymore
        meeting_points.pop(k)
        lin_name = list(mp.incoming)[0]
        lout_name = list(mp.outcoming)[0]

        lin_name = resolve_alias(lin_name)
        lout_name = resolve_alias(lout_name)

        # print(' -> %s and %s meet at %s' % (lin_name, lout_name, mp))
        # print('%s and %s meet at %s' % (lin_name, lout_name, k))

        def get(it):
            if it in root.children:
                return root.children[it]
            else:
                return created[it]

        lin = get(lin_name)
        lout = get(lout_name)

        # name = 'alias%s' % (len(aliases))
        # name = '%s-%s' % (lin_name, lout_name)
        name = 'L%d' % (len(created))
        width = lin.width

        control_points = lin.control_points + lout.control_points[1:]
        ls = LaneSegment(width=width, control_points=control_points)
        created[name] = ls

        aliases[lin_name] = name
        aliases[lout_name] = name
        # print('new alias %s' % name)
    #
    # print('created: %s' % list(created))
    # print('aliases: %s' % aliases)
    root2 = PlacedObject()
    for k, v in created.items():
        if not k in aliases:
            root2.set_object(k, v, ground_truth=SE2Transform.identity())

    for k, v in root.children.items():
        if not k in aliases:
            root2.set_object(k, v, ground_truth=SE2Transform.identity())

    import networkx as nx
    G = nx.MultiDiGraph()

    k2name = {}
    for i, (k, mp) in enumerate(meeting_points.items()):
        node_name = 'P%d' % i
        k2name[k] = node_name

        G.add_node(node_name, point=mp.point)

    ls2start = {}
    ls2end = {}
    for i, (k, mp) in enumerate(meeting_points.items()):
        node_name = k2name[k]

        for l in mp.incoming:
            ls2end[resolve_alias(l)] = node_name
        for l in mp.outcoming:
            ls2start[resolve_alias(l)] = node_name

    # print(ls2start)
    # print(ls2end)

    for l in ls2start:
        n1 = ls2start[l]
        n2 = ls2end[l]
        G.add_edge(n1, n2, lane=l)

    return SkeletonGraphResult(root=root, root2=root2, G=G)
 def transform_point(p):
     q = p.as_SE2()
     q2 = np.dot(M, q)
     p2 = SE2Transform.from_SE2(q2)
     return p2
Example #15
0
def discretize(tran: SE2Transform) -> PointLabel:
    def D(x):
        return np.round(x, decimals=2)

    p, theta = geo.translation_angle_from_SE2(tran.as_SE2())
    return D(p[0]), D(p[1]), D(np.cos(theta)), D(np.sin(theta))
Example #16
0
def get_skeleton_graph(po: DuckietownMap) -> SkeletonGraphResult:
    """ Returns a graph with the lane segments of the map """

    root = PlacedObject()

    meeting_points: Dict[str, MeetingPoint] = defaultdict(MeetingPoint)

    for i, it in enumerate(iterate_by_class(po, LaneSegment)):
        lane_segment = cast(LaneSegment, it.object)
        assert isinstance(lane_segment, LaneSegment), lane_segment

        absolute_pose = it.transform_sequence.asmatrix2d()

        lane_segment_transformed = transform_lane_segment(lane_segment, absolute_pose)

        identity = SE2Transform.identity()
        name = "ls%03d" % i
        root.set_object(name, lane_segment_transformed, ground_truth=identity)

        p0 = discretize(lane_segment_transformed.control_points[0])
        p1 = discretize(lane_segment_transformed.control_points[-1])

        if not p0 in meeting_points:
            meeting_points[p0] = MeetingPoint(
                set(), set(), set(), lane_segment_transformed.control_points[0], None, None,
            )
        if not p1 in meeting_points:
            meeting_points[p1] = MeetingPoint(
                set(), set(), set(), lane_segment_transformed.control_points[-1], None, None,
            )

        # meeting_points[p0].point = lane_segment_transformed.control_points[0]
        meeting_points[p0].outcoming.add(name)
        # meeting_points[p1].point = lane_segment_transformed.control_points[-1]
        meeting_points[p1].incoming.add(name)

        meeting_points[p0].connects_to.add(p1)

        tile_coords = [_ for _ in it.transform_sequence.transforms if isinstance(_, TileCoords)]
        if not tile_coords:
            raise ZException(p0=p0, p1=p1, transforms=it.transform_sequence.transforms)
        tile_coord = tile_coords[0]
        ij = tile_coord.i, tile_coord.j
        meeting_points[p0].into_tile = ij
        meeting_points[p1].from_tile = ij

    for k, mp in meeting_points.items():
        if (len(mp.incoming) == 0) or (len(mp.outcoming) == 0):
            msg = "Completeness assumption violated at point %s: %s" % (k, mp)
            raise Exception(msg)

    G0 = graph_for_meeting_points(meeting_points)
    # compress the lanes which are contiguous

    aliases = {}

    created = {}

    def resolve_alias(x):
        return x if x not in aliases else resolve_alias(aliases[x])

    for k, mp in list(meeting_points.items()):
        # continue
        if not (len(mp.incoming) == 1 and len(mp.outcoming) == 1):
            continue

        # not necessary anymore
        meeting_points.pop(k)
        lin_name = list(mp.incoming)[0]
        lout_name = list(mp.outcoming)[0]

        lin_name = resolve_alias(lin_name)
        lout_name = resolve_alias(lout_name)

        # print(' -> %s and %s meet at %s' % (lin_name, lout_name, mp))
        # print('%s and %s meet at %s' % (lin_name, lout_name, k))

        def get(it):
            if it in root.children:
                return root.children[it]
            else:
                return created[it]

        lin = get(lin_name)
        lout = get(lout_name)

        # name = 'alias%s' % (len(aliases))
        # name = '%s-%s' % (lin_name, lout_name)
        name = "L%d" % (len(created))
        width = lin.width

        control_points = lin.control_points + lout.control_points[1:]
        ls = LaneSegment(width=width, control_points=control_points)
        created[name] = ls

        aliases[lin_name] = name
        aliases[lout_name] = name
        # print('new alias %s' % name)
    #
    # print('created: %s' % list(created))
    # print('aliases: %s' % aliases)
    root2 = PlacedObject()
    for k, v in created.items():
        if not k in aliases:
            root2.set_object(k, v, ground_truth=SE2Transform.identity())

    for k, v in root.children.items():
        if not k in aliases:
            root2.set_object(k, v, ground_truth=SE2Transform.identity())

    G = nx.MultiDiGraph()

    k2name = {}
    for i, (k, mp) in enumerate(meeting_points.items()):
        node_name = "P%d" % i
        k2name[k] = node_name

        G.add_node(node_name, point=mp.point)

    ls2start = {}
    ls2end = {}
    for i, (k, mp) in enumerate(meeting_points.items()):
        node_name = k2name[k]

        for l in mp.incoming:
            ls2end[resolve_alias(l)] = node_name
        for l in mp.outcoming:
            ls2start[resolve_alias(l)] = node_name

    # print(ls2start)
    # print(ls2end)

    for l in ls2start:
        n1 = ls2start[l]
        n2 = ls2end[l]
        G.add_edge(n1, n2, lane=l)

    return SkeletonGraphResult(root=root, root2=root2, G=G, G0=G0)
def construct_map(yaml_data, tile_size):
    dm = DuckietownMap(tile_size)

    tiles = yaml_data['tiles']
    assert len(tiles) > 0
    assert len(tiles[0]) > 0

    # Create the grid
    A = len(tiles)
    B = len(tiles[0])
    tm = TileMap(H=B, W=A)

    templates = load_tile_types()
    for a, row in enumerate(tiles):
        if len(row) != B:
            msg = "each row of tiles must have the same length"
            raise ValueError(msg)

        # For each tile in this row
        for b, tile in enumerate(row):
            tile = tile.strip()

            if tile == 'empty':
                continue

            DEFAULT_ORIENT = 'E'  # = no rotation
            if '/' in tile:
                kind, orient = tile.split('/')
                kind = kind.strip()
                orient = orient.strip()

                drivable = True
            elif '4' in tile:
                kind = '4way'
                # angle = 2
                orient = DEFAULT_ORIENT
                drivable = True
            else:
                kind = tile
                # angle = 0
                orient = DEFAULT_ORIENT
                drivable = False

            tile = Tile(kind=kind, drivable=drivable)
            if kind in templates:
                tile.set_object(kind,
                                templates[kind],
                                ground_truth=SE2Transform.identity())
            else:
                pass
                # msg = 'Could not find %r in %s' % (kind, templates)
                # logger.debug(msg)

            tm.add_tile(b, (A - 1) - a, orient, tile)

    def go(obj_name, desc):
        obj = get_object(desc)
        transform = get_transform(desc, tm, tile_size)
        dm.set_object(obj_name, obj, ground_truth=transform)

    objects = yaml_data.get('objects', [])
    if isinstance(objects, list):
        for obj_idx, desc in enumerate(objects):
            kind = desc['kind']
            obj_name = 'ob%02d-%s' % (obj_idx, kind)
            go(obj_name, desc)
    elif isinstance(objects, dict):
        for obj_name, desc in objects.items():
            go(obj_name, desc)
    else:
        raise ValueError(objects)

    for it in list(iterate_by_class(tm, Tile)):
        ob = it.object
        if 'slots' in ob.children:
            slots = ob.children['slots']
            for k, v in list(slots.children.items()):
                if not v.children:
                    slots.remove_object(k)
            if not slots.children:
                ob.remove_object('slots')

    dm.set_object('tilemap', tm, ground_truth=Scale2D(tile_size))
    return dm
 def lane_pose_from_SE2Transform(self,
                                 qt: SE2Transform,
                                 tol=0.001) -> LanePose:
     return self.lane_pose_from_SE2(qt.as_SE2(), tol=tol)