Setup

In [1]:
import duckietown_world as dw
import logging
dw.logger.setLevel(logging.CRITICAL)
import contracts; contracts.disable_all()
INFO:dt-world:duckietown-world 1.0.14

Better visualization of output

In [2]:
%%html
<style>
pre {line-height: 90%}
</style>
In [3]:
def draw_html(po, outdir=None, area=None):
    if outdir is None:
        outdir = 'out-draw_html/%s' % id(po)
    dw.draw_static(po, outdir, area=area)

    from IPython.display import IFrame, display

    iframe = IFrame(src=outdir + '/drawing.html', width='100%', height=600)
    display(iframe)

Map representation

Let's load a map and see how data is represented inside:

In [4]:
m = dw.load_map('small_loop')
draw_html(m)

The map is a DuckietownMap which is an instance of PlacedObject. All spatially situated objects are instances of this class.

In [5]:
type(m).mro() # see all superclasses of the object
Out[5]:
[duckietown_world.world_duckietown.duckietown_map.DuckietownMap,
 duckietown_world.geo.placed_object.PlacedObject,
 duckietown_serialization_ds1.serialization1.Serializable,
 duckietown_serialization_ds1.serialization1.Serializable0,
 object]

Children

The data is arranged in a hierarchy. We can visualize using the function get_object_tree. The hierarchy is more deep, but we clip it to 2 levels:

In [6]:
print(dw.get_object_tree(m, levels=2))
DuckietownMap

└ tilemap ┐ TileMap
          │ 
          │ ├ tile-2-2 ┐ Tile
          │ │          └───────
          │ ├ tile-2-0 ┐ Tile
          │ │          └───────
          │ ├ tile-2-1 ┐ Tile
          │ │          └───────
          │ ├ tile-0-0 ┐ Tile
          │ │          └───────
          │ ├ tile-0-1 ┐ Tile
          │ │          └───────
          │ ├ tile-0-2 ┐ Tile
          │ │          └───────
          │ ├ tile-1-1 ┐ Tile
          │ │          └───────
          │ ├ tile-1-0 ┐ Tile
          │ │          └───────
          │ └ tile-1-2 ┐ Tile
          │            └───────
          └──────────────────────

The children are available in the children variable:

In [7]:
m.children
Out[7]:
{'tilemap': TileMap(H=3,W=3)}
In [8]:
m.children['tilemap'].children
Out[8]:
{'tile-0-0': Tile(kind=curve_left,drivable=True),
 'tile-0-1': Tile(kind=straight,drivable=True),
 'tile-0-2': Tile(kind=curve_left,drivable=True),
 'tile-1-0': Tile(kind=straight,drivable=True),
 'tile-1-1': Tile(kind=asphalt,drivable=False),
 'tile-1-2': Tile(kind=straight,drivable=True),
 'tile-2-0': Tile(kind=curve_left,drivable=True),
 'tile-2-1': Tile(kind=straight,drivable=True),
 'tile-2-2': Tile(kind=curve_left,drivable=True)}

You can use the notation below to get a child in a compact way:

In [9]:
tile = m['tilemap/tile-0-0']

In this case we can see how a Tile has a child curve_left with a child curve with two children lane1 and lane2:

In [10]:
print(dw.get_object_tree(tile, attributes=False, levels=10))
Tile

└ curve_left ┐ PlacedObject
             │ 
             │ └ curve ┐ PlacedObject
             │         │
             │         │ ├ lane2 ┐ LaneSegment
             │         │ │       └──────────────
             │         │ └ lane1 ┐ LaneSegment
             │         │         └──────────────
             │         └──────────────────────────
             └──────────────────────────────────────
In [11]:
draw_html(tile)
In [12]:
draw_html(tile['curve_left/curve'])
In [13]:
lane = tile['curve_left/curve/lane2']
draw_html(lane)
In [14]:
lane.width
Out[14]:
0.47
In [15]:
lane.control_points
Out[15]:
[SE2Transform([-0.5, -0.25],0.0),
 SE2Transform([0.0, -0.25],0.0),
 SE2Transform([0.25, 0.0],1.57079632679),
 SE2Transform([0.25, 0.5],1.57079632679)]

Parametrization of lanes

The lane is parametrized with a parameter beta that interpolates among the control points.

Here we create an animation of the center point for different betas.

In [16]:
import numpy as np
npoints = len(lane.control_points)
betas = list(np.linspace(-1, npoints + 1, 20))

transforms = []
for beta in betas:
    p = lane.center_point(beta)
    transform = dw.SE2Transform.from_SE2(p)
    transforms.append(transform)

ground_truth = dw.SampledSequence(betas, transforms)
lane.set_object('traveling-point', dw.PlacedObject(), ground_truth=ground_truth)
draw_html(lane)

Scrub the timeline to see the animation.

In [17]: