Пример #1
0
def svg1():
    outdir = get_comptests_output_dir()
    control_points = [
        SE2Transform.from_SE2(geo.SE2_from_translation_angle([0, 0], 0)),
        SE2Transform.from_SE2(geo.SE2_from_translation_angle([1, 0], 0)),
        SE2Transform.from_SE2(geo.SE2_from_translation_angle([2, -1], np.deg2rad(-90))),
    ]

    width = 0.3

    ls = LaneSegment(width, control_points)

    area = RectangularArea((-1, -2), (3, 2))
    draw_static(ls, outdir, area=area)
def get_flattened_measurement_graph(po, include_root_to_self=False):
    G = get_meausurements_graph(po)
    G2 = nx.DiGraph()
    root_name = ()
    for name in G.nodes():
        if name == root_name:
            continue
        path = nx.shortest_path(G, (), name)
        transforms = []
        for i in range(len(path) - 1):
            a = path[i]
            b = path[i + 1]
            edges = G.get_edge_data(a, b)

            k = list(edges)[0]
            v = edges[k]
            sr = v['attr_dict']['sr'].transform

            transforms.append(sr)

        from duckietown_world import TransformSequence
        if any(isinstance(_, Sequence) for _ in transforms):
            res = VariableTransformSequence(transforms)
        else:
            res = TransformSequence(transforms)
        G2.add_edge(root_name, name, transform_sequence=res)

    if include_root_to_self:
        from duckietown_world import SE2Transform
        transform_sequence = SE2Transform.identity()
        G2.add_edge(root_name, root_name, transform_sequence=transform_sequence)

    return G2
Пример #3
0
def center_point1():
    outdir = get_comptests_output_dir()
    templates = load_tile_types()

    for k, v in templates.items():
        if isinstance(v, LaneSegment):

            area = RectangularArea((-2, -2), (3, 3))
            dest = os.path.join(outdir, k)

            N = len(v.control_points)
            betas = list(np.linspace(-2, N + 1, 20))
            betas.extend(range(N))
            betas = sorted(betas)
            transforms = []
            for timestamp in betas:
                beta = timestamp
                p = v.center_point(beta)
                # print('%s: %s' % (beta, geo.SE2.friendly(p)))

                transform = SE2Transform.from_SE2(p)
                transforms.append(transform)

            c = SampledSequence[SE2Transform](betas, transforms)
            v.set_object("a", PlacedObject(), ground_truth=c)
            draw_static(v, dest, area=area)
Пример #4
0
    def __init__(self, children=None, spatial_relations=None):
        children = children or {}
        spatial_relations = spatial_relations or {}

        self.children = children

        for k, v in list(spatial_relations.items()):
            from .transforms import Transform
            if isinstance(v, Transform):
                if k in self.children:
                    sr = GroundTruth(a=(), b=(k, ), transform=v)
                    spatial_relations[k] = sr
                else:
                    msg = 'What is the "%s" referring to?' % k
                    raise ValueError(msg)

        self.spatial_relations = spatial_relations

        if not spatial_relations:
            for child in self.children:
                from duckietown_world import SE2Transform
                sr = GroundTruth(a=(),
                                 b=(child, ),
                                 transform=SE2Transform.identity())
                self.spatial_relations[child] = sr
Пример #5
0
    def __post_init__(self):
        from .transforms import Transform

        for k, v in list(self.spatial_relations.items()):
            if isinstance(v, Transform):
                if k in self.children:
                    b: Tuple[str, ...] = (k,)
                    sr = GroundTruth(a=root, b=b, transform=v)
                    self.spatial_relations[k] = sr
                else:
                    msg = f'What is the "{k}" referring to?'
                    raise ValueError(msg)

        if not self.spatial_relations:
            for child in self.children:
                from duckietown_world import SE2Transform

                sr = GroundTruth(a=root, b=(child,), transform=SE2Transform.identity())
                self.spatial_relations[child] = sr
Пример #6
0
def test_pwm1():
    parameters = get_DB18_nominal(delay=0)

    # initial configuration
    init_pose = np.array([0, 0.8])
    init_vel = np.array([0, 0])

    q0 = geo.SE2_from_R2(init_pose)
    v0 = geo.se2_from_linear_angular(init_vel, 0)
    tries = {
        "straight_50": (PWMCommands(+0.5, 0.5)),
        "straight_max": (PWMCommands(+1.0, +1.0)),
        "straight_over_max": (PWMCommands(+1.5, +1.5)),
        "pure_left": (PWMCommands(motor_left=-0.5, motor_right=+0.5)),
        "pure_right": (PWMCommands(motor_left=+0.5, motor_right=-0.5)),
        "slight-forward-left": (PWMCommands(motor_left=0, motor_right=0.25)),
        "faster-forward-right": (PWMCommands(motor_left=0.5, motor_right=0)),
        # 'slight-right': (PWMCommands(-0.1, 0.1)),
    }
    dt = 0.03
    t_max = 10

    map_data_yaml = """

    tiles:
    - [floor/W,floor/W, floor/W, floor/W, floor/W] 
    - [straight/W   , straight/W   , straight/W, straight/W, straight/W]
    - [floor/W,floor/W, floor/W, floor/W, floor/W]
    tile_size: 0.61
    """

    map_data = yaml.load(map_data_yaml)

    root = construct_map(map_data)

    timeseries = {}
    for id_try, commands in tries.items():
        seq = integrate_dynamics(parameters, q0, v0, dt, t_max, commands)

        ground_truth = seq.transform_values(
            lambda t: SE2Transform.from_SE2(t[0]))
        poses = seq.transform_values(lambda t: t[0])
        velocities = get_velocities_from_sequence(poses)
        linear = velocities.transform_values(linear_from_se2)
        angular = velocities.transform_values(angular_from_se2)
        # print(linear.values)
        # print(angular.values)
        root.set_object(id_try, DB18(), ground_truth=ground_truth)

        sequences = {}
        sequences["motor_left"] = seq.transform_values(
            lambda _: commands.motor_left)
        sequences["motor_right"] = seq.transform_values(
            lambda _: commands.motor_right)
        plots = TimeseriesPlot(f"{id_try} - PWM commands", "pwm_commands",
                               sequences)
        timeseries[f"{id_try} - commands"] = plots

        sequences = {}
        sequences["linear_velocity"] = linear
        sequences["angular_velocity"] = angular
        plots = TimeseriesPlot(f"{id_try} - Velocities", "velocities",
                               sequences)
        timeseries[f"{id_try} - velocities"] = plots

    outdir = os.path.join(get_comptests_output_dir(), "together")
    draw_static(root, outdir, timeseries=timeseries)
Пример #7
0
    def evaluate(self, agent, outdir, episodes=None):
        """
        Evaluates the agent on the map inicialised in __init__
        :param agent: Agent to be evaluated, passed to self._collect_trajectory(agent,...)
        :param outdir: Directory for logged outputs (trajectory plots + numeric data)
        :param episodes: Number of evaluation episodes, if None, it is determined based on self.start_poses
        """
        if not os.path.exists(outdir):
            os.makedirs(outdir)
        if episodes is None:
            episodes = len(self.start_poses.get(self.map_name, []))
        totals = {}
        for i in range(episodes):
            episode_path, episode_orientations, episode_timestamps = self._collect_trajectory(
                agent, i)
            logger.info("Episode {}/{} sampling completed".format(
                i + 1, episodes))
            if len(episode_timestamps) <= 1:
                continue
            episode_path = np.stack(episode_path)
            episode_orientations = np.stack(episode_orientations)
            # Convert them to SampledSequences
            transforms_sequence = []
            for j in range(len(episode_path)):
                transforms_sequence.append(
                    SE2Transform(episode_path[j], episode_orientations[j]))
            transforms_sequence = SampledSequence.from_iterator(
                enumerate(transforms_sequence))
            transforms_sequence.timestamps = episode_timestamps

            _outdir = outdir
            if outdir is not None and episodes > 1:
                _outdir = os.path.join(outdir, "Trajectory_{}".format(i + 1))
            evaluated = self._eval_poses_sequence(transforms_sequence,
                                                  outdir=_outdir)
            logger.info("Episode {}/{} plotting completed".format(
                i + 1, episodes))
            totals = self._extract_total_episode_eval_metrics(
                evaluated, totals, display_outputs=True)

        # Calculate the median total metrics
        median_totals = {}
        mean_totals = {}
        stdev_totals = {}
        for key, value in totals.items():
            median_totals[key] = np.median(value)
            mean_totals[key] = np.mean(value)
            stdev_totals[key] = np.std(value)
        # Save results to file
        with open(os.path.join(outdir, "total_metrics.json"),
                  "w") as json_file:
            json.dump(
                {
                    'median_totals': median_totals,
                    'mean_totals': mean_totals,
                    'stdev_totals': stdev_totals,
                    'episode_totals': totals
                },
                json_file,
                indent=2)

        logger.info("\nMedian total metrics: \n {}".format(
            pretty_print(median_totals)))
        logger.info("\nMean total metrics: \n {}".format(
            pretty_print(mean_totals)))
        logger.info("\nStandard deviation of total metrics: \n {}".format(
            pretty_print(stdev_totals)))
Пример #8
0
def interpret_map_data(data):
    tiles = 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

            if '/' in tile:
                kind, orient = tile.split('/')
                kind = kind.strip()
                orient = orient.strip()
                # angle = ['S', 'E', 'N', 'W'].index(orient)
                drivable = True
            elif '4' in tile:
                kind = '4way'
                # angle = 2
                orient = 'N'
                drivable = True
            else:
                kind = tile
                # angle = 0
                orient = 'S'
                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)

            # if drivable:
            #     tile['curves'] = self._get_curve(i, j)
            # self.drivable_tiles.append(tile)
    #
    # self._load_objects(self.map_data)
    #

    # # Get the starting tile from the map, if specified
    # self.start_tile = None
    # if 'start_tile' in self.map_data:
    #     coords = self.map_data['start_tile']
    #     self.start_tile = self._get_tile(*coords)

    # # Arrays for checking collisions with N static objects
    # # (Dynamic objects done separately)
    # # (N x 2): Object position used in calculating reward
    # self.collidable_centers = []
    #
    # # (N x 2 x 4): 4 corners - (x, z) - for object's boundbox
    # self.collidable_corners = []
    #
    # # (N x 2 x 2): two 2D norms for each object (1 per axis of boundbox)
    # self.collidable_norms = []
    #
    # # (N): Safety radius for object used in calculating reward
    # self.collidable_safety_radii = []

    # For each object

    for obj_idx, desc in enumerate(data.get('objects', [])):
        kind = desc['kind']

        pos = desc['pos']

        rotate = desc['rotate']
        transform = SE2Transform([float(pos[0]), float(tm.W - pos[1])], rotate)

        # x, z = pos[0:2]
        #
        # i = int(np.floor(x))
        # j = int(np.floor(z))
        # dx = x - i
        # dy = z - j
        #
        # z = pos[2] if len(pos) == 3 else 0.0

        # optional = desc.get('optional', False)
        # height = desc.get('height', None)

        # pos = ROAD_TILE_SIZE * np.array((x, y, z))

        # Load the mesh
        # mesh = ObjMesh.get(kind)

        # TODO
        # if 'height' in desc:
        #     scale = desc['height'] / mesh.max_coords[1]
        # else:
        #     scale = desc['scale']
        # assert not ('height' in desc and 'scale' in desc), "cannot specify both height and scale"

        # static = desc.get('static', True)

        # obj_desc = {
        #     'kind': kind,
        #     # 'mesh': mesh,
        #     'pos': pos,
        #     'scale': scale,
        #     'y_rot': rotate,
        #     'optional': optional,
        #     'static': static,
        # }

        if kind == "trafficlight":
            status = Constant("off")
            obj = TrafficLight(status)
        else:
            kind2klass = {
                'duckie': Duckie,
                'cone': Cone,
                'barrier': Barrier,
                'building': Building,
                'duckiebot': DB18,
                'sign_left_T_intersect': SignLeftTIntersect,
                'sign_right_T_intersect': SignRightTIntersect,
                'sign_T_intersect': SignTIntersect,
                'sign_4_way_intersect': Sign4WayIntersect,
                'sign_t_light_ahead': SingTLightAhead,
                'sign_stop': SignStop,
                'tree': Tree,
                'house': House,
                'bus': Bus,
                'truck': Truck,
            }
            if kind in kind2klass:
                klass = kind2klass[kind]
                obj = klass()
            else:
                logger.debug('Do not know special kind %s' % kind)
                obj = GenericObject(kind=kind)
        obj_name = 'ob%02d-%s' % (obj_idx, kind)
        # tile = tm[(i, j)]
        # transform = TileRelativeTransform([dx, dy], z, rotate)

        tm.set_object(obj_name, obj, ground_truth=transform)

        # obj = None
        # if static:
        #     if kind == "trafficlight":
        #         obj = TrafficLightObj(obj_desc, self.domain_rand, SAFETY_RAD_MULT)
        #     else:
        #         obj = WorldObj(obj_desc, self.domain_rand, SAFETY_RAD_MULT)
        # else:
        #     obj = DuckieObj(obj_desc, self.domain_rand, SAFETY_RAD_MULT, ROAD_TILE_SIZE)
        #
        # self.objects.append(obj)

        # Compute collision detection information

        # angle = rotate * (math.pi / 180)

        # Find drivable tiles object could intersect with

    return tm
Пример #9
0
    slot = int(slot)

    rotation = rotation or 0
    rotation = int(rotation)
    # bug in the map file
    # rotation = rotation + 90
    sign = dict(kind=kind,
                tag={
                    '~TagInstance':
                    dict(tag_id=int(tag_ID),
                         family='36h11',
                         size=APRIL_TAG_SIZE)
                },
                attach=dict(tile=[x, y], slot=slot))

    sign['pose'] = SE2Transform([0, 0], np.deg2rad(rotation)).as_json_dict()

    objects['tag%02d' % i] = sign

in_file = open("AprilTag position duckietown.csv", "rb")
reader = csv.reader(in_file)
data = list(reader)[1:]
CM = 0.01
origin = -5 * CM, -15.5 * CM
# Tag ID,Quadrant,x location,Y-location,Roation

# FAMILY = 'default'
# SIZE = 0.035
for entry in data:
    tag_ID, quadrant, x, y, rotation = entry
    x = float(x) + origin[0]
Пример #10
0
def get_SE2transform(x: PlatformDynamics) -> SE2Transform:
    check_isinstance(x, PlatformDynamics)
    q, v = x.TSE2_from_state()
    return SE2Transform.from_SE2(q)